This is an automated email from the ASF dual-hosted git repository. kmccusker pushed a commit to branch issue19 in repository https://gitbox.apache.org/repos/asf/incubator-milagro-MPC.git
commit 5698837e3599564958af6071949131d3c08671ed Author: Kealan McCusker <[email protected]> AuthorDate: Fri Feb 21 14:16:52 2020 +0000 add BLS Python wrapper --- Dockerfile | 2 +- python/amcl/bls.py | 234 +++++++++++++++++++++++++++++++++++++++++ python/examples/example_bls.py | 149 ++++++++++++++++++++++++++ scripts/buildAMCL.sh | 2 +- src/CMakeLists.txt | 7 ++ 5 files changed, 392 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 83ab0a2..ae6c905 100755 --- a/Dockerfile +++ b/Dockerfile @@ -58,7 +58,7 @@ RUN git clone https://github.com/apache/incubator-milagro-crypto-c.git && \ cd incubator-milagro-crypto-c && \ mkdir build && \ cd build && \ - cmake -D CMAKE_BUILD_TYPE=Release -D BUILD_SHARED_LIBS=ON -D AMCL_CHUNK=64 -D AMCL_CURVE="BLS381,SECP256K1" -D AMCL_RSA="" -D BUILD_PAILLIER=ON -D BUILD_PYTHON=ON -D BUILD_BLS=ON -D BUILD_WCC=OFF -D BUILD_MPIN=OFF -D BUILD_X509=OFF -D CMAKE_INSTALL_PREFIX=/usr/local .. && \ + cmake -D CMAKE_BUILD_TYPE=Release -D BUILD_SHARED_LIBS=ON -D AMCL_CHUNK=64 -D AMCL_CURVE="BLS381,SECP256K1" -D AMCL_RSA="" -D BUILD_PAILLIER=ON -D BUILD_PYTHON=OFF -D BUILD_BLS=ON -D BUILD_WCC=OFF -D BUILD_MPIN=OFF -D BUILD_X509=OFF -D CMAKE_INSTALL_PREFIX=/usr/local .. && \ make && \ make test ARGS=-j8 && \ make install diff --git a/python/amcl/bls.py b/python/amcl/bls.py new file mode 100755 index 0000000..2a53ac4 --- /dev/null +++ b/python/amcl/bls.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python3 + +""" +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +""" + + +""" +bls + +This module use cffi to access the c functions in the BLS library. + +There is also an example usage program in this file. + +""" + +import platform +from amcl import core_utils + +_ffi = core_utils._ffi +_ffi.cdef(""" +extern int BLS_BLS381_KEY_PAIR_GENERATE(csprng *RNG,octet* S,octet *W); +extern int BLS_BLS381_SIGN(octet *SIG,octet *m,octet *S); +extern int BLS_BLS381_VERIFY(octet *SIG,octet *m,octet *W); +extern int BLS_BLS381_ADD_G1(octet *R1,octet *R2,octet *R); +extern int BLS_BLS381_ADD_G2(octet *W1,octet *W2,octet *W); +""") + +if (platform.system() == 'Windows'): + _libamcl_bls_BLS381 = _ffi.dlopen("libamcl_bls_BLS381.dll") +elif (platform.system() == 'Darwin'): + _libamcl_bls_BLS381 = _ffi.dlopen("libamcl_bls_BLS381.dylib") +else: + _libamcl_bls_BLS381 = _ffi.dlopen("libamcl_bls_BLS381.so") + +# Group Size +BGS = 48 +# Field Size +BFS = 48 + +CURVE_SECURITY = 128 + +G1LEN = BFS + 1 + +if CURVE_SECURITY == 128: + G2LEN = 4 * BFS + +if CURVE_SECURITY == 192: + G2LEN = 8 * BFS + +if CURVE_SECURITY == 256: + G2LEN = 16 * BFS + + +def key_pair_generate(rng, sk=None): + """Generate key pair + + Generate key pair + + Args:: + + rng: Pointer to cryptographically secure pseudo-random number generator instance + sk: secret key. Externally generated + + Returns:: + + error_code: error from the C function + sk: secret key + pk: public key + + Raises: + + """ + if sk: + sk1, sk1_val = core_utils.make_octet(None, sk) + rng = _ffi.NULL + else: + sk1, sk1val = core_utils.make_octet(BGS) + + pk1, pk1val = core_utils.make_octet(G2LEN) + error_code = _libamcl_bls_BLS381.BLS_BLS381_KEY_PAIR_GENERATE(rng, sk1, pk1) + + sk = core_utils.to_str(sk1) + pk = core_utils.to_str(pk1) + + # clear memory + core_utils.clear_octet(sk1) + core_utils.clear_octet(pk1) + + return error_code, sk, pk + + +def sign(message, sk): + """Calculate a signature + + Generate key pair + + Args:: + + message: Message to sign + sk: BLS secret key + + Returns:: + + error_code: Zero for success or else an error code + signature: BLS signature + + Raises: + + """ + m, m_val = core_utils.make_octet(None, message) + sk1, sk1_val = core_utils.make_octet(None, sk) + signature1, signature1_val = core_utils.make_octet(G1LEN) + error_code = _libamcl_bls_BLS381.BLS_BLS381_SIGN(signature1, m, sk1) + + signature = core_utils.to_str(signature1) + + # clear memory + core_utils.clear_octet(sk1) + core_utils.clear_octet(signature1) + + return error_code, signature + + +def verify(signature, message, pk): + """Verify a signature + + Verify a signature + + Args:: + + message: Message to verify + signature: BLS signature + pk: BLS public key + + Returns:: + + error_code: Zero for success or else an error code + + Raises: + + """ + m, m_val = core_utils.make_octet(None, message) + pk1, pk1_val = core_utils.make_octet(None, pk) + signature1, signature1_val = core_utils.make_octet(None, signature) + error_code = _libamcl_bls_BLS381.BLS_BLS381_VERIFY(signature1, m, pk1) + + # clear memory + core_utils.clear_octet(pk1) + core_utils.clear_octet(signature1) + + return error_code + + +def add_G1(R1, R2): + """Add two members from the group G1 + + Add two members from the group G1 + + Args:: + + R1: member of G1 + R2: member of G1 + + Returns:: + + R: member of G1. R = R1+R2 + error_code: Zero for success or else an error code + + Raises: + + """ + R11, R11_val = core_utils.make_octet(None, R1) + R21, R21_val = core_utils.make_octet(None, R2) + R1, R1_val = core_utils.make_octet(G1LEN) + error_code = _libamcl_bls_BLS381.BLS_BLS381_ADD_G1(R11, R21, R1) + + R = core_utils.to_str(R1) + + # clear memory + core_utils.clear_octet(R11) + core_utils.clear_octet(R21) + core_utils.clear_octet(R1) + + return error_code, R + + +def add_G2(R1, R2): + """Add two members from the group G2 + + Add two members from the group G2 + + Args:: + + R1: member of G2 + R2: member of G2 + + Returns:: + + R: member of G2. R = R1+R2 + error_code: Zero for success or else an error code + + Raises: + + """ + R11, R11_val = core_utils.make_octet(None, R1) + R21, R21_val = core_utils.make_octet(None, R2) + R1, R1_val = core_utils.make_octet(G2LEN) + error_code = _libamcl_bls_BLS381.BLS_BLS381_ADD_G2(R11, R21, R1) + + R = core_utils.to_str(R1) + + # clear memory + core_utils.clear_octet(R11) + core_utils.clear_octet(R21) + core_utils.clear_octet(R1) + + return error_code, R + diff --git a/python/examples/example_bls.py b/python/examples/example_bls.py new file mode 100755 index 0000000..33075d1 --- /dev/null +++ b/python/examples/example_bls.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 + +""" +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +""" + +import os +import sys + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) + +from amcl import core_utils, bls + +if __name__ == "__main__": + # Print hex values + DEBUG = False + + # Seed + seed_hex = "78d0fb6705ce77dee47d03eb5b9c5d30" + seed = bytes.fromhex(seed_hex) + + # Message + message = b"test message" + + # random number generator + rng = core_utils.create_csprng(seed) + + # Generate key pairs + rtn, sk1, pktmp = bls.key_pair_generate(rng) + if rtn != 0: + print("Error: key_pair_generate {}".format(rtn)) + raise SystemExit(0) + print("sk1: {}".format(sk1.hex())) + print("pktmp: {}".format(pktmp.hex())) + + rtn, sk1, pk1 = bls.key_pair_generate(rng, sk1) + if rtn != 0: + print("Error: key_pair_generate {}".format(rtn)) + raise SystemExit(0) + print("sk1: {}".format(sk1.hex())) + print("pk1: {}".format(pk1.hex())) + + rtn, sk2, pk2 = bls.key_pair_generate(rng) + if rtn != 0: + print("Error: key_pair_generate {}".format(rtn)) + raise SystemExit(0) + print("sk2: {}".format(sk2.hex())) + print("pk2: {}".format(pk2.hex())) + + rtn, sk3, pk3 = bls.key_pair_generate(rng) + if rtn != 0: + print("Error: key_pair_generate {}".format(rtn)) + raise SystemExit(0) + print("sk3: {}".format(sk3.hex())) + print("pk3: {}".format(pk3.hex())) + + # Sign and verify + rtn, sig1 = bls.sign(message, sk1) + if rtn != 0: + print("Error: sign {}".format(rtn)) + raise SystemExit(0) + print("sig1: {}".format(sig1.hex())) + + rtn = bls.verify(sig1, message, pk1) + if rtn != 0: + print("Error: Invalid signature {}".format(rtn)) + raise SystemExit(0) + print("Success: Signature is valid") + + rtn, sig2 = bls.sign(message, sk2) + if rtn != 0: + print("Error: sign {}".format(rtn)) + raise SystemExit(0) + print("sig2: {}".format(sig2.hex())) + + rtn = bls.verify(sig2, message, pk2) + if rtn != 0: + print("Error: Invalid signature {}".format(rtn)) + raise SystemExit(0) + print("Success: Signature is valid") + + rtn, sig3 = bls.sign(message, sk3) + if rtn != 0: + print("Error: sign {}".format(rtn)) + raise SystemExit(0) + print("sig3: {}".format(sig3.hex())) + + rtn = bls.verify(sig3, message, pk3) + if rtn != 0: + print("Error: Invalid signature {}".format(rtn)) + raise SystemExit(0) + print("Success: Signature is valid") + + # Add Signatures + rtn, sig12 = bls.add_G1(sig1, sig2) + if rtn != 0: + print("Error: add_G1 {}".format(rtn)) + raise SystemExit(0) + print("sig12: {}".format(sig12.hex())) + + rtn, sig123 = bls.add_G1(sig12, sig3) + if rtn != 0: + print("Error: add_G1 {}".format(rtn)) + raise SystemExit(0) + print("sig123: {}".format(sig123.hex())) + + # Add Public keys + rtn, pk12 = bls.add_G2(pk1, pk2) + if rtn != 0: + print("Error: add_G2 {}".format(rtn)) + raise SystemExit(0) + print("pk12: {}".format(pk12.hex())) + + rtn, pk123 = bls.add_G2(pk12, pk3) + if rtn != 0: + print("Error: add_G2 {}".format(rtn)) + raise SystemExit(0) + print("pk123: {}".format(pk123.hex())) + + # Verify aggretated values + rtn = bls.verify(sig123, message, pk123) + if rtn != 0: + print("Error: Invalid aggregated signature {}".format(rtn)) + raise SystemExit(0) + print("Success: Aggregated signature is valid") + + # Clear memory + core_utils.kill_csprng(rng) + del sk1 + del pk1 + del sk2 + del pk2 + del sk3 + del pk3 diff --git a/scripts/buildAMCL.sh b/scripts/buildAMCL.sh index 137d09e..e612cb5 100755 --- a/scripts/buildAMCL.sh +++ b/scripts/buildAMCL.sh @@ -15,7 +15,7 @@ git clone https://github.com/apache/incubator-milagro-crypto-c.git cd incubator-milagro-crypto-c mkdir build cd build -cmake -D CMAKE_BUILD_TYPE=Debug -D BUILD_SHARED_LIBS=ON -D AMCL_CHUNK=64 -D AMCL_CURVE="BLS381,SECP256K1" -D AMCL_RSA="" -D BUILD_PAILLIER=ON -D BUILD_PYTHON=ON -D BUILD_BLS=ON -D BUILD_WCC=OFF -D BUILD_MPIN=ON -D BUILD_X509=OFF -D CMAKE_INSTALL_PREFIX=/usr/local .. +cmake -D CMAKE_BUILD_TYPE=Debug -D BUILD_SHARED_LIBS=ON -D AMCL_CHUNK=64 -D AMCL_CURVE="BLS381,SECP256K1" -D AMCL_RSA="" -D BUILD_PAILLIER=ON -D BUILD_PYTHON=OFF -D BUILD_BLS=ON -D BUILD_WCC=OFF -D BUILD_MPIN=ON -D BUILD_X509=OFF -D CMAKE_INSTALL_PREFIX=/usr/local .. make make test ARGS=-j8 sudo make install diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1311df2..f6c45db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,3 +39,10 @@ install(TARGETS ${target} DESTINATION lib PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +if(BUILD_PYTHON) + message(STATUS "Copy ${target} library to python directory for testing") + add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/lib*" "${PROJECT_BINARY_DIR}/python/test") + add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/lib*" "${PROJECT_BINARY_DIR}/python/benchmark") + add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/lib*" "${PROJECT_BINARY_DIR}/python/examples") +endif(BUILD_PYTHON)
