Merge tag 'v1.51' into mm

2merge
Hao Chen 3 years ago
commit fec57a49f5
  1. 25
      .github/workflows/main.yml
  2. 3
      .gitignore
  3. 17
      .travis.yml
  4. 420
      CMakeLists.txt
  5. 106
      Makefile
  6. 548
      api.md
  7. 67
      build.sh
  8. 88
      cmake/FindGMP.cmake
  9. 68
      common.mk
  10. 115
      ffi/cs/bn256.cs
  11. 31
      ffi/cs/mcl.sln
  12. 1007
      ffi/cs/mcl/mcl.cs
  13. 13
      ffi/cs/mcl/mcl.csproj
  14. 24
      ffi/cs/readme.md
  15. 408
      ffi/cs/test/test.cs
  16. 28
      ffi/cs/test/test.csproj
  17. 3
      ffi/go/mcl/init.go
  18. 681
      ffi/go/mcl/mcl.go
  19. 145
      ffi/go/mcl/mcl_test.go
  20. 104
      ffi/java/Bn256Test.java
  21. 2
      ffi/java/ElgamalTest.java
  22. 41
      ffi/java/Makefile
  23. 160
      ffi/java/MclTest.java
  24. 39
      ffi/java/android/jni/Android.mk
  25. 4
      ffi/java/android/jni/Application.mk
  26. 31
      ffi/java/bn256.i
  27. 249
      ffi/java/bn256_impl.hpp
  28. 1542
      ffi/java/bn256_wrap.cxx
  29. 67
      ffi/java/com/herumi/mcl/CipherText.java
  30. 38
      ffi/java/com/herumi/mcl/Elgamal.java
  31. 51
      ffi/java/com/herumi/mcl/ElgamalJNI.java
  32. 105
      ffi/java/com/herumi/mcl/Fp.java
  33. 113
      ffi/java/com/herumi/mcl/Fr.java
  34. 93
      ffi/java/com/herumi/mcl/G1.java
  35. 89
      ffi/java/com/herumi/mcl/G2.java
  36. 81
      ffi/java/com/herumi/mcl/GT.java
  37. 128
      ffi/java/com/herumi/mcl/Mcl.java
  38. 14
      ffi/java/com/herumi/mcl/MclConstants.java
  39. 120
      ffi/java/com/herumi/mcl/MclJNI.java
  40. 87
      ffi/java/com/herumi/mcl/PrivateKey.java
  41. 83
      ffi/java/com/herumi/mcl/PublicKey.java
  42. 26
      ffi/java/com/herumi/mcl/SWIGTYPE_p_bool.java
  43. 19
      ffi/java/elgamal_impl.hpp
  44. 124
      ffi/java/elgamal_wrap.cxx
  45. 77
      ffi/java/java.md
  46. 6
      ffi/java/make_wrap.bat
  47. 29
      ffi/java/mcl.i
  48. 436
      ffi/java/mcl_impl.hpp
  49. 2681
      ffi/java/mcl_wrap.cxx
  50. 9
      ffi/java/run-bn256.bat
  51. 9
      ffi/java/run-mcl.bat
  52. 9
      ffi/python/Makefile
  53. 7
      ffi/python/readme.md
  54. 2
      ffi/python/she.py
  55. 5
      include/cybozu/atoi.hpp
  56. 146
      include/cybozu/atomic.hpp
  57. 5
      include/cybozu/exception.hpp
  58. 626
      include/cybozu/file.hpp
  59. 2
      include/cybozu/hash.hpp
  60. 13
      include/cybozu/inttype.hpp
  61. 3
      include/cybozu/itoa.hpp
  62. 3
      include/cybozu/mutex.hpp
  63. 26
      include/cybozu/option.hpp
  64. 30
      include/cybozu/random_generator.hpp
  65. 59
      include/cybozu/sha2.hpp
  66. 785
      include/cybozu/socket.hpp
  67. 2
      include/cybozu/stream.hpp
  68. 281
      include/cybozu/time.hpp
  69. 60
      include/mcl/aggregate_sig.hpp
  70. 76
      include/mcl/ahe.hpp
  71. 10
      include/mcl/array.hpp
  72. 117
      include/mcl/bn.h
  73. 915
      include/mcl/bn.hpp
  74. 34
      include/mcl/config.hpp
  75. 102
      include/mcl/conversion.hpp
  76. 87
      include/mcl/curve_type.h
  77. 1664
      include/mcl/ec.hpp
  78. 105
      include/mcl/ecdsa.h
  79. 257
      include/mcl/ecdsa.hpp
  80. 28
      include/mcl/ecparam.hpp
  81. 2
      include/mcl/elgamal.hpp
  82. 352
      include/mcl/fp.hpp
  83. 715
      include/mcl/fp_tower.hpp
  84. 205
      include/mcl/gmp_util.hpp
  85. 200
      include/mcl/impl/bn_c_impl.hpp
  86. 572
      include/mcl/mapto_wb19.hpp
  87. 57
      include/mcl/op.hpp
  88. 46
      include/mcl/operator.hpp
  89. 27
      include/mcl/she.h
  90. 317
      include/mcl/she.hpp
  91. 78
      include/mcl/util.hpp
  92. 163
      include/mcl/vint.hpp
  93. 34
      include/mcl/window_method.hpp
  94. 6
      misc/Makefile
  95. 234
      misc/low_test.cpp
  96. 119
      misc/she/memo.txt
  97. 14
      misc/she/she-api-ja.md
  98. 24
      misc/she/she-api.md
  99. 18
      misc/snark-p.py
  100. 29
      mklib.bat
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,25 @@
name: test
on: [push]
jobs:
build:
name: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: lscpu
- run: sudo apt install valgrind
- run: make bin/pairing.exe -j4
- run: valgrind bin/pairing.exe
- run: make clean
# - run: wget https://software.intel.com/content/dam/develop/external/us/en/documents/downloads/sde-external-8.63.0-2021-01-18-lin.tar.bz2
# - run: bzip2 -dc sde-external-8.63.0-2021-01-18-lin.tar.bz2 | tar xvf -
# - run: make bin/bn_test.exe DEBUG=1 -j4
# - run: sde-external-8.63.0-2021-01-18-lin/sde64 -hsw -- bin/bn_test.exe
- run: make test_ci DEBUG=1 -j4
- run: make clean
- run: make test_ci DEBUG=1 -j4 CXX=clang++
- run: make clean
# - run: make test_go
# - run: sudo apt install openjdk-8-jdk
# - run: make -C ffi/java test JAVA_INC=-I/usr/lib/jvm/java-8-openjdk-amd64/include

3
.gitignore vendored

@ -11,3 +11,6 @@ GTAGS
*.exe
*.swp
.cvsignore
build/
external/
Testing/

@ -1,17 +0,0 @@
sudo: true
dist: trusty
language: cpp
compiler:
- gcc
- clang
addons:
apt:
packages:
- libgmp-dev
script:
- make test_ci DEBUG=1 -j3
- make clean
- make test_ci CFLAGS_USER=-DMCL_DONT_USE_XBYAK -j3
- make clean
- make test_go

@ -1,209 +1,395 @@
cmake_minimum_required (VERSION 3.0)
project(mcl CXX ASM)
set(SRCS src/fp.cpp)
cmake_minimum_required (VERSION 3.8)
project(mcl
VERSION 1.22
LANGUAGES CXX C ASM)
set(CMAKE_BUILD_TYPE "Release")
option(
MCL_MAX_BIT_SIZE
"max bit size for Fp"
0
384
)
option(
DOWNLOAD_SOURCE
"download cybozulib_ext"
MCL_STATIC_LIB
"build static library"
OFF
)
if(MSVC)
option(
MCL_DOWNLOAD_SOURCE
"download cybozulib_ext"
OFF
)
endif()
option(
USE_OPENSSL
MCL_USE_OPENSSL
"use openssl"
ON
OFF
)
option(
USE_GMP
MCL_USE_GMP
"use gmp"
ON
)
option(
USE_ASM
MCL_USE_ASM
"use asm"
ON
)
option(
USE_XBYAK
MCL_USE_XBYAK
"use xbyak"
ON
)
option(
USE_LLVM
MCL_USE_LLVM
"use base64.ll with -DCMAKE_CXX_COMPILER=clang++"
OFF
)
option(
ONLY_LIB
"only lib"
MCL_BUILD_SAMPLE
"Build mcl samples"
OFF
)
option(
MCL_BUILD_TESTING
"Build mcl tests"
OFF
)
if(MSVC)
option(
MCL_MSVC_RUNTIME_DLL
"use dynamic runtime /MD in msvc builds"
OFF
)
endif()
if(MSVC)
set(MCL_CYBOZULIB_EXT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../cybozulib_ext"
CACHE PATH "external cybozulib_ext directory")
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
if(USE_LLVM)
if(MCL_USE_LLVM AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
message(WARNING "MCL_USE_LLVM will not be used: requiring clang/clang++.")
endif()
add_library(mcl SHARED src/fp.cpp)
add_library(mcl::mcl ALIAS mcl)
target_compile_definitions(mcl PUBLIC MCL_NO_AUTOLINK MCLBN_NO_AUTOLINK)
target_include_directories(mcl PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:$CMAKE_INSTALL_DIR/include>)
set_target_properties(mcl PROPERTIES
POSITION_INDEPENDENT_CODE ON)
set_target_properties(mcl PROPERTIES
OUTPUT_NAME mcl
VERSION ${mcl_VERSION}
SOVERSION ${mcl_VERSION_MAJOR})
# For semantics of ABI compatibility including when you must bump SOVERSION, see:
# https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B#The_Do.27s_and_Don.27ts
add_library(mcl_st STATIC src/fp.cpp)
add_library(mcl::mcl_st ALIAS mcl_st)
target_compile_definitions(mcl_st PUBLIC MCL_NO_AUTOLINK MCLBN_NO_AUTOLINK)
target_include_directories(mcl_st PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:$CMAKE_INSTALL_DIR/include>)
set_target_properties(mcl_st PROPERTIES
OUTPUT_NAME mcl
POSITION_INDEPENDENT_CODE ON)
#set_target_properties(mcl_st PROPERTIES PREFIX "lib")
if(MCL_USE_LLVM AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_executable(gen src/gen.cpp)
add_custom_target(base64.ll
DEPENDS gen
SOURCES base64.ll
)
target_include_directories(gen PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include)
if(MCL_USE_GMP)
find_package(GMP REQUIRED)
target_link_libraries(gen PRIVATE GMP::GMPXX GMP::GMP)
endif()
add_custom_command(OUTPUT base64.ll
COMMAND gen > base64.ll
)
add_custom_target(base64.o
DEPENDS base64.ll
SOURCES base64.o
)
DEPENDS gen
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_custom_target(gen_base64.ll
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/base64.ll)
add_custom_command(OUTPUT base64.o
COMMAND ${CMAKE_CXX_COMPILER} -c -o base64.o base64.ll -O3 -fPIC
)
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/base64.ll
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_custom_target(gen_base64.o
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/base64.o)
target_link_libraries(mcl PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/base64.o)
add_dependencies(mcl gen_base64.o)
target_link_libraries(mcl_st PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/base64.o)
add_dependencies(mcl_st gen_base64.o)
endif()
if(MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MT /W4 /Oy /Ox /EHsc /GS- /Zi /DNDEBUG /DNOMINMAX")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /MTd /W4 /DNOMINMAX")
link_directories(${CMAKE_SOURCE_DIR}/../cybozulib_ext/lib)
link_directories(${CMAKE_SOURCE_DIR}/lib)
else()
if("${CFLAGS_OPT_USER}" STREQUAL "")
set(CFLAGS_OPT_USER "-O3 -DNDEBUG -march=native")
if(MCL_MSVC_RUNTIME_DLL)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MD /Oy /Ox /EHsc /GS- /Zi /DNDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /MDd")
else()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MT /Oy /Ox /EHsc /GS- /Zi /DNDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /MTd")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith ${CFLAGS_OPT_USER}")
target_compile_definitions(mcl PUBLIC NOMINMAX)
target_compile_definitions(mcl_st PUBLIC NOMINMAX)
# set compiler flags for warnings level
set(MCL_COMPILE_OPTIONS /W4)
target_compile_options(mcl PRIVATE ${MCL_COMPILE_OPTIONS})
target_compile_options(mcl_st PRIVATE ${MCL_COMPILE_OPTIONS})
else()
# Set compiler flags for warnings
set(MCL_COMPILE_OPTIONS -Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align
-Wwrite-strings -Wfloat-equal -Wpointer-arith -DNDEBUG -O3 -fPIC)
target_compile_options(mcl PRIVATE ${MCL_COMPILE_OPTIONS})
target_compile_options(mcl_st PRIVATE ${MCL_COMPILE_OPTIONS})
set_target_properties(mcl PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO)
set_target_properties(mcl_st PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO)
target_compile_features(mcl PUBLIC cxx_std_11)
target_compile_features(mcl_st PUBLIC cxx_std_11)
if(${MCL_MAX_BIT_SIZE} GREATER 0)
add_definitions(-DMCL_MAX_BIT_SIZE=${MCL_MAX_BIT_SIZE})
target_compile_definitions(mcl PUBLIC MCL_MAX_BIT_SIZE=${MCL_MAX_BIT_SIZE})
target_compile_definitions(mcl_st PUBLIC MCL_MAX_BIT_SIZE=${MCL_MAX_BIT_SIZE})
endif()
if(USE_LLVM)
add_definitions(-DMCL_USE_LLVM=1 -DMCL_LLVM_BMI2=0)
elseif(USE_ASM)
if(MCL_USE_LLVM AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1 MCL_LLVM_BMI2=0)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1 MCL_LLVM_BMI2=0)
elseif(MCL_USE_ASM)
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
add_definitions(-DMCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/aarch64.s)
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1)
target_sources(mcl PRIVATE src/asm/aarch64.s)
target_sources(mcl_st PRIVATE src/asm/aarch64.s)
set(CPU arch64)
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm")
add_definitions(-DMCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/arm.s)
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1)
target_sources(mcl PRIVATE src/asm/arm.s)
target_sources(mcl_st PRIVATE src/asm/arm.s)
set(CPU arm)
elseif(APPLE)
add_definitions(-DMCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/x86-64mac.s src/asm/x86-64mac.bmi2.s)
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1)
target_sources(mcl PRIVATE src/asm/x86-64mac.s src/asm/x86-64mac.bmi2.s)
target_sources(mcl_st PRIVATE src/asm/x86-64mac.s src/asm/x86-64mac.bmi2.s)
set(CPU x86-64)
elseif(UNIX)
add_definitions(-DMCL_USE_LLVM=1)
set(SRCS ${SRCS} src/asm/x86-64.s src/asm/x86-64.bmi2.s)
target_compile_definitions(mcl PUBLIC MCL_USE_LLVM=1)
target_compile_definitions(mcl_st PUBLIC MCL_USE_LLVM=1)
target_sources(mcl PRIVATE src/asm/x86-64.s src/asm/x86-64.bmi2.s)
target_sources(mcl_st PRIVATE src/asm/x86-64.s src/asm/x86-64.bmi2.s)
set(CPU x86-64)
endif()
endif()
if(USE_GMP)
set(EXT_LIBS ${EXT_LIBS} gmp gmpxx)
if(MCL_USE_GMP)
find_package(GMP REQUIRED)
target_link_libraries(mcl PUBLIC GMP::GMPXX GMP::GMP)
target_link_libraries(mcl_st PUBLIC GMP::GMPXX GMP::GMP)
endif()
if(USE_OPENSSL)
set(EXT_LIBS ${EXT_LIBS} crypto)
if(MCL_USE_OPENSSL)
find_package(OpenSSL REQUIRED)
target_link_libraries(mcl PUBLIC OpenSSL::Crypto)
target_link_libraries(mcl_st PUBLIC OpenSSL::Crypto)
endif()
endif()
if(NOT USE_GMP)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER")
if(NOT MCL_USE_GMP)
target_compile_definitions(mcl PUBLIC MCL_USE_VINT MCL_VINT_FIXED_BUFFER)
target_compile_definitions(mcl_st PUBLIC MCL_USE_VINT MCL_VINT_FIXED_BUFFER)
endif()
if(NOT USE_OPENSSL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_DONT_USE_OPENSSL")
if(NOT MCL_USE_OPENSSL)
target_compile_definitions(mcl PUBLIC MCL_DONT_USE_OPENSSL)
target_compile_definitions(mcl_st PUBLIC MCL_DONT_USE_OPENSSL)
endif()
if(NOT USE_XBYAK)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_DONT_USE_XBYAK")
if(NOT MCL_USE_XBYAK)
target_compile_definitions(mcl PUBLIC MCL_DONT_USE_XBYAK)
target_compile_definitions(mcl_st PUBLIC MCL_DONT_USE_XBYAK)
endif()
if(DOWNLOAD_SOURCE)
if(MCL_DOWNLOAD_SOURCE)
if(MSVC)
set(CYBOZULIB_EXT_DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/cybozulib_ext)
set(CYBOZULIB_EXT_TAG release20170521)
set(FILES config.h gmp-impl.h gmp-mparam.h gmp.h gmpxx.h longlong.h mpir.h mpirxx.h)
foreach(file IN ITEMS ${FILES})
file(DOWNLOAD https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/include/${file} ${mcl_SOURCE_DIR}/include/cybozulib_ext/${file})
file(DOWNLOAD https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/include/${file} ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include/${file})
message("download cybozulib_ext/" ${file})
endforeach()
set(FILES aes.h applink.c asn1.h asn1_mac.h asn1t.h bio.h blowfish.h bn.h buffer.h camellia.h cast.h cmac.h cms.h comp.h conf.h conf_api.h crypto.h des.h des_old.h dh.h dsa.h dso.h dtls1.h e_os2.h ebcdic.h ec.h ecdh.h ecdsa.h engine.h err.h evp.h hmac.h idea.h krb5_asn.h kssl.h lhash.h md4.h md5.h mdc2.h modes.h obj_mac.h objects.h ocsp.h opensslconf.h opensslv.h ossl_typ.h pem.h pem2.h pkcs12.h pkcs7.h pqueue.h rand.h rc2.h rc4.h ripemd.h rsa.h safestack.h seed.h sha.h srp.h srtp.h ssl.h ssl2.h ssl23.h ssl3.h stack.h symhacks.h tls1.h ts.h txt_db.h ui.h ui_compat.h whrlpool.h x509.h x509_vfy.h x509v3.h)
foreach(file IN ITEMS ${FILES})
file(DOWNLOAD https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/include/openssl/${file} ${mcl_SOURCE_DIR}/include/cybozulib_ext/openssl/${file})
file(DOWNLOAD
https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/include/openssl/${file} ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include/openssl/${file})
message("download cybozulib_ext/openssl/" ${file})
endforeach()
set(FILES mpir.lib mpirxx.lib mpirxx.pdb ssleay32.lib libeay32.lib mpir.pdb)
foreach(file IN ITEMS ${FILES})
file(DOWNLOAD https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/lib/mt/14/${file} ${mcl_SOURCE_DIR}/lib/mt/14/${file})
file(DOWNLOAD
https://raw.githubusercontent.com/herumi/cybozulib_ext/${CYBOZULIB_EXT_TAG}/lib/mt/14/${file} ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/${file})
message("download lib/mt/14/" ${file})
endforeach()
if(MSVC)
include_directories(
${mcl_SOURCE_DIR}/include/cybozulib_ext
)
endif()
# mpir
add_library(cybozulib_ext::mpir STATIC IMPORTED)
set_target_properties(cybozulib_ext::mpir PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include
IMPORTED_LOCATION ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/mpir.lib)
# mpirxx
add_library(cybozulib_ext::mpirxx STATIC IMPORTED)
set_target_properties(cybozulib_ext::mpirxx PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include
IMPORTED_LOCATION ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/mpirxx.lib)
# libeay32
add_library(cybozulib_ext::libeay32 STATIC IMPORTED)
set_target_properties(cybozulib_ext::libeay32 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include
IMPORTED_LOCATION ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/libeay32.lib)
# ssleay32
add_library(cybozulib_ext::ssleay32 STATIC IMPORTED)
set_target_properties(cybozulib_ext::ssleay32 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CYBOZULIB_EXT_DOWNLOAD_DIR}/include
IMPORTED_LOCATION ${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14/ssleay32.lib)
# abstracted cybozulib_ext libraries
add_library(windows_specific INTERFACE)
add_library(mcl::windows_specific ALIAS windows_specific)
target_link_libraries(windows_specific INTERFACE
-LIBPATH:${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib
-LIBPATH:${CYBOZULIB_EXT_DOWNLOAD_DIR}/lib/mt/14
cybozulib_ext::mpir
cybozulib_ext::mpirxx
cybozulib_ext::libeay32
cybozulib_ext::ssleay32)
target_link_libraries(mcl PUBLIC mcl::windows_specific)
target_link_libraries(mcl_st PUBLIC mcl::windows_specific)
endif()
else()
if(MSVC)
include_directories(
${mcl_SOURCE_DIR}/../cybozulib_ext/include
)
# mpir
add_library(cybozulib_ext::mpir STATIC IMPORTED)
set_target_properties(cybozulib_ext::mpir PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MCL_CYBOZULIB_EXT_DIR}/include
IMPORTED_LOCATION ${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14/mpir.lib)
# mpirxx
add_library(cybozulib_ext::mpirxx STATIC IMPORTED)
set_target_properties(cybozulib_ext::mpirxx PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MCL_CYBOZULIB_EXT_DIR}/include
IMPORTED_LOCATION ${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14/mpirxx.lib)
# libeay32
add_library(cybozulib_ext::libeay32 STATIC IMPORTED)
set_target_properties(cybozulib_ext::libeay32 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MCL_CYBOZULIB_EXT_DIR}/include
IMPORTED_LOCATION ${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14/libeay32.lib)
# ssleay32
add_library(cybozulib_ext::ssleay32 STATIC IMPORTED)
set_target_properties(cybozulib_ext::ssleay32 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${MCL_CYBOZULIB_EXT_DIR}/include
IMPORTED_LOCATION ${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14/ssleay32.lib)
# abstracted cybozulib_ext libraries
add_library(windows_specific INTERFACE)
add_library(mcl::windows_specific ALIAS windows_specific)
target_link_libraries(windows_specific INTERFACE
-LIBPATH:${MCL_CYBOZULIB_EXT_DIR}/lib
-LIBPATH:${MCL_CYBOZULIB_EXT_DIR}/lib/mt/14
cybozulib_ext::mpir
cybozulib_ext::mpirxx
cybozulib_ext::libeay32
cybozulib_ext::ssleay32)
target_link_libraries(mcl PUBLIC mcl::windows_specific)
target_link_libraries(mcl_st PUBLIC mcl::windows_specific)
endif()
endif()
include_directories(
${mcl_SOURCE_DIR}/include
)
# mclbnXXX
foreach(bit IN ITEMS 256 384 384_256)
if (MCL_STATIC_LIB)
add_library(mclbn${bit} STATIC src/bn_c${bit}.cpp)
else()
add_library(mclbn${bit} SHARED src/bn_c${bit}.cpp)
endif()
add_library(mcl::mclbn${bit} ALIAS mclbn${bit})
set_target_properties(mclbn${bit} PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO)
target_compile_options(mclbn${bit} PRIVATE ${MCL_COMPILE_OPTIONS})
target_compile_definitions(mclbn${bit}
PUBLIC MCL_NO_AUTOLINK MCLBN_NO_AUTOLINK)
target_link_libraries(mclbn${bit} PUBLIC mcl::mcl)
set_target_properties(mclbn${bit} PROPERTIES
VERSION ${mcl_VERSION}
SOVERSION ${mcl_VERSION_MAJOR})
endforeach()
if(USE_LLVM)
add_library(mcl SHARED ${SRCS} base64.o)
add_library(mcl_st STATIC ${SRCS} base64.o)
add_dependencies(mcl base64.o)
add_dependencies(mcl_st base64.o)
if(MSVC)
install(TARGETS mcl mcl_st mclbn256 mclbn384 mclbn384_256 windows_specific
EXPORT mclTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib)
else()
add_library(mcl SHARED ${SRCS})
add_library(mcl_st STATIC ${SRCS})
install(TARGETS mcl mcl_st mclbn256 mclbn384 mclbn384_256
EXPORT mclTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION lib)
endif()
target_link_libraries(mcl ${EXT_LIBS})
target_link_libraries(mcl_st ${EXT_LIBS})
set_target_properties(mcl_st PROPERTIES OUTPUT_NAME mcl)
#set_target_properties(mcl_st PROPERTIES PREFIX "lib")
#set_target_properties(mcl PROPERTIES OUTPUT_NAME mcl VERSION 1.0.0 SOVERSION 1)
# For semantics of ABI compatibility including when you must bump SOVERSION, see:
# https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B#The_Do.27s_and_Don.27ts
install(DIRECTORY include/mcl
DESTINATION include
FILES_MATCHING PATTERN "*.hpp"
PATTERN "curve_type.h"
PATTERN "bn.h"
PATTERN "bn_c256.h"
PATTERN "bn_c384_256.h"
PATTERN "bn_c384.h")
install(DIRECTORY include/cybozu
DESTINATION include
FILES_MATCHING PATTERN "*.hpp")
set(LIBS mcl ${EXT_LIBS})
foreach(bit IN ITEMS 256 384 384_256 512)
add_library(mclbn${bit} SHARED src/bn_c${bit}.cpp)
target_link_libraries(mclbn${bit} ${LIBS})
add_executable(bn_c${bit}_test test/bn_c${bit}_test.cpp)
target_link_libraries(bn_c${bit}_test mclbn${bit})
endforeach()
install(EXPORT mclTargets
FILE mclTargets.cmake
NAMESPACE mcl::
DESTINATION lib/cmake/mcl)
file(GLOB MCL_HEADERS include/mcl/*.hpp include/mcl/bn.h include/mcl/curve_type.h)
file(GLOB CYBOZULIB_HEADERS include/cybozu/*.hpp)
install(TARGETS mcl DESTINATION lib)
install(TARGETS mcl_st DESTINATION lib)
install(TARGETS mclbn256 DESTINATION lib)
install(TARGETS mclbn384 DESTINATION lib)
install(TARGETS mclbn384_256 DESTINATION lib)
install(TARGETS mclbn512 DESTINATION lib)
install(FILES ${MCL_HEADERS} DESTINATION include/mcl)
install(FILES include/mcl/impl/bn_c_impl.hpp DESTINATION include/mcl/impl)
install(FILES ${CYBOZULIB_HEADERS} DESTINATION include/cybozu)
if(NOT ONLY_LIB)
set(TEST_BASE fp_test ec_test fp_util_test window_method_test elgamal_test fp_tower_test gmp_test bn_test glv_test)
#set(TEST_BASE bn_test)
foreach(base IN ITEMS ${TEST_BASE})
add_executable(
${base}
test/${base}.cpp
)
target_link_libraries(
${base}
${LIBS}
)
endforeach()
# support local build-tree export to allow import from external projects
export(EXPORT mclTargets
FILE mclTargets.cmake
NAMESPACE mcl::)
set(CMAKE_EXPORT_PACKAGE_REGISTRY ON)
export(PACKAGE mcl)
# Tests
if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MCL_BUILD_TESTING)
AND BUILD_TESTING)
enable_testing()
add_subdirectory(test)
endif()
if(MCL_BUILD_SAMPLE)
# sample code
add_subdirectory(sample)
endif()

@ -2,14 +2,19 @@ include common.mk
LIB_DIR=lib
OBJ_DIR=obj
EXE_DIR=bin
SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c512.cpp she_c256.cpp
TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp ecdsa_test.cpp conversion_test.cpp
SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c384_256.cpp bn_c512.cpp she_c256.cpp
TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp conversion_test.cpp
TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c384_256_test.cpp bn_c512_test.cpp
TEST_SRC+=she_c256_test.cpp she_c384_test.cpp she_c384_256_test.cpp
TEST_SRC+=aggregate_sig_test.cpp array_test.cpp
TEST_SRC+=bls12_test.cpp
TEST_SRC+=ecdsa_c_test.cpp
TEST_SRC+=mapto_wb19_test.cpp
TEST_SRC+=modp_test.cpp
LIB_OBJ=$(OBJ_DIR)/fp.o
ifeq ($(MCL_STATIC_CODE),1)
LIB_OBJ+=obj/static_code.o
TEST_SRC=bls12_test.cpp
endif
ifeq ($(CPU),x86-64)
MCL_USE_XBYAK?=1
TEST_SRC+=mont_fp_test.cpp sq_test.cpp
@ -28,6 +33,13 @@ endif
ifeq ($(MCL_USE_XBYAK),0)
CFLAGS+=-DMCL_DONT_USE_XBYAK
endif
ifeq ($(MCL_USE_PROF),1)
CFLAGS+=-DMCL_USE_PROF
endif
ifeq ($(MCL_USE_PROF),2)
CFLAGS+=-DMCL_USE_PROF -DXBYAK_USE_VTUNE -I /opt/intel/vtune_amplifier/include/
LDFLAGS+=-L /opt/intel/vtune_amplifier/lib64 -ljitprofiling -ldl
endif
##################################################################
MCL_LIB=$(LIB_DIR)/libmcl.a
MCL_SNAME=mcl
@ -53,20 +65,19 @@ SHE384_LIB=$(LIB_DIR)/libmclshe384.a
SHE384_SLIB=$(LIB_DIR)/lib$(SHE384_SNAME).$(LIB_SUF)
SHE384_256_LIB=$(LIB_DIR)/libmclshe384_256.a
SHE384_256_SLIB=$(LIB_DIR)/lib$(SHE384_256_SNAME).$(LIB_SUF)
ECDSA_LIB=$(LIB_DIR)/libmclecdsa.a
SHE_LIB_ALL=$(SHE256_LIB) $(SHE256_SLIB) $(SHE384_LIB) $(SHE384_SLIB) $(SHE384_256_LIB) $(SHE384_256_SLIB)
all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN384_256_LIB) $(BN384_256_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE_LIB_ALL) $(ECDSA_LIB)
all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN384_256_LIB) $(BN384_256_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE_LIB_ALL)
#LLVM_VER=-3.8
LLVM_LLC=llc$(LLVM_VER)
LLVM_OPT=opt$(LLVM_VER)
LLVM_OPT_VERSION=$(shell $(LLVM_OPT) --version 2>/dev/null | awk '/version/ {print $$3}')
LLVM_OPT_VERSION=$(shell $(LLVM_OPT) --version 2>/dev/null | awk '/version/ { split($$3,a,"."); print a[1]}')
GEN_EXE=src/gen
GEN_EXE_OPT=-u $(BIT)
# incompatibility between llvm 3.4 and the later version
ifneq ($(LLVM_OPT_VERSION),)
ifeq ($(shell expr $(LLVM_OPT_VERSION) \< 3.5.0),1)
GEN_EXE_OPT+=-old
ifeq ($(shell expr $(LLVM_OPT_VERSION) \>= 9),1)
GEN_EXE_OPT+=-ver 0x90
endif
endif
ifeq ($(OS),mac)
@ -78,7 +89,10 @@ ifneq ($(CPU),)
ASM_SRC=$(ASM_SRC_PATH_NAME).s
endif
ASM_OBJ=$(OBJ_DIR)/$(CPU).o
LIB_OBJ=$(OBJ_DIR)/fp.o
ifeq ($(OS),mac-m1)
ASM_SRC=src/base64.ll
ASM_OBJ=$(OBJ_DIR)/base64.o
endif
BN256_OBJ=$(OBJ_DIR)/bn_c256.o
BN384_OBJ=$(OBJ_DIR)/bn_c384.o
BN384_256_OBJ=$(OBJ_DIR)/bn_c384_256.o
@ -86,7 +100,6 @@ BN512_OBJ=$(OBJ_DIR)/bn_c512.o
SHE256_OBJ=$(OBJ_DIR)/she_c256.o
SHE384_OBJ=$(OBJ_DIR)/she_c384.o
SHE384_256_OBJ=$(OBJ_DIR)/she_c384_256.o
ECDSA_OBJ=$(OBJ_DIR)/ecdsa_c.o
FUNC_LIST=src/func.list
ifeq ($(findstring $(OS),mingw64/cygwin),)
MCL_USE_LLVM?=1
@ -98,7 +111,9 @@ ifeq ($(MCL_USE_LLVM),1)
LIB_OBJ+=$(ASM_OBJ)
# special case for intel with bmi2
ifeq ($(INTEL),1)
LIB_OBJ+=$(OBJ_DIR)/$(CPU).bmi2.o
ifneq ($(MCL_STATIC_CODE),1)
LIB_OBJ+=$(OBJ_DIR)/$(CPU).bmi2.o
endif
endif
endif
LLVM_SRC=src/base$(BIT).ll
@ -173,9 +188,6 @@ $(SHE384_SLIB): $(SHE384_OBJ) $(MCL_LIB)
$(SHE384_256_SLIB): $(SHE384_256_OBJ) $(MCL_LIB)
$(PRE)$(CXX) -o $@ $(SHE384_256_OBJ) $(MCL_LIB) -shared $(LDFLAGS) $(SHE384_256_SLIB_LDFLAGS)
$(ECDSA_LIB): $(ECDSA_OBJ)
$(AR) $@ $(ECDSA_OBJ)
$(BN256_SLIB): $(BN256_OBJ) $(MCL_SLIB)
$(PRE)$(CXX) -o $@ $(BN256_OBJ) -shared $(LDFLAGS) $(BN256_SLIB_LDFLAGS)
@ -227,8 +239,20 @@ else
endif
$(GEN_EXE): src/gen.cpp src/llvm_gen.hpp
$(CXX) -o $@ $< $(CFLAGS)
$(CXX) -o $@ $< $(CFLAGS) -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER
src/dump_code: src/dump_code.cpp src/fp.cpp src/fp_generator.hpp
$(CXX) -o $@ src/dump_code.cpp src/fp.cpp -g -I include -DMCL_DUMP_JIT -DMCL_MAX_BIT_SIZE=384 -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER
src/static_code.asm: src/dump_code
$< > $@
obj/static_code.o: src/static_code.asm
nasm $(NASM_ELF_OPT) -o $@ $<
bin/static_code_test.exe: test/static_code_test.cpp src/fp.cpp obj/static_code.o
$(CXX) -o $@ -O3 $^ -g -DMCL_DONT_USE_XBYAK -DMCL_STATIC_CODE -DMCL_MAX_BIT_SIZE=384 -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -I include -Wall -Wextra
asm: $(LLVM_SRC)
$(LLVM_OPT) -O3 -o - $(LLVM_SRC) | $(LLVM_LLC) -O3 $(LLVM_FLAGS) -x86-asm-syntax=intel
@ -287,8 +311,8 @@ $(EXE_DIR)/bn_c384_256_test.exe: $(OBJ_DIR)/bn_c384_256_test.o $(BN384_256_LIB)
$(EXE_DIR)/bn_c512_test.exe: $(OBJ_DIR)/bn_c512_test.o $(BN512_LIB) $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(BN512_LIB) $(MCL_LIB) $(LDFLAGS)
$(EXE_DIR)/pairing_c.exe: $(OBJ_DIR)/pairing_c.o $(BN256_LIB) $(MCL_LIB)
$(PRE)$(CC) $< -o $@ $(BN256_LIB) $(MCL_LIB) $(LDFLAGS) -lstdc++
$(EXE_DIR)/pairing_c.exe: $(OBJ_DIR)/pairing_c.o $(BN384_256_LIB) $(MCL_LIB)
$(PRE)$(CC) $< -o $@ $(BN384_256_LIB) $(MCL_LIB) $(LDFLAGS) -lstdc++
$(EXE_DIR)/she_c256_test.exe: $(OBJ_DIR)/she_c256_test.o $(SHE256_LIB) $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(SHE256_LIB) $(MCL_LIB) $(LDFLAGS)
@ -299,9 +323,6 @@ $(EXE_DIR)/she_c384_test.exe: $(OBJ_DIR)/she_c384_test.o $(SHE384_LIB) $(MCL_LIB
$(EXE_DIR)/she_c384_256_test.exe: $(OBJ_DIR)/she_c384_256_test.o $(SHE384_256_LIB) $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(SHE384_256_LIB) $(MCL_LIB) $(LDFLAGS)
$(EXE_DIR)/ecdsa_c_test.exe: $(OBJ_DIR)/ecdsa_c_test.o $(ECDSA_LIB) $(MCL_LIB) src/ecdsa_c.cpp include/mcl/ecdsa.hpp include/mcl/ecdsa.h
$(PRE)$(CXX) $< -o $@ $(ECDSA_LIB) $(MCL_LIB) $(LDFLAGS)
$(OBJ_DIR)/modp_test.o: test/modp_test.cpp
$(PRE)$(CXX) -c $< -o $@ -MMD -MP -MF $(@:.o=.d) -DMCL_USE_VINT -DMCL_MAX_BIT_SIZE=384 -DMCL_VINT_64BIT_PORTABLE -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -I./include -O2 $(CFLAGS_WARN)
@ -313,7 +334,7 @@ sample: $(SAMPLE_EXE) $(MCL_LIB)
TEST_EXE=$(addprefix $(EXE_DIR)/,$(TEST_SRC:.cpp=.exe))
test_ci: $(TEST_EXE)
@sh -ec 'for i in $(TEST_EXE); do echo $$i; env LSAN_OPTIONS=verbosity=1:log_threads=1 $$i; done'
@sh -ec 'for i in $(TEST_EXE); do echo $$i; env LSAN_OPTIONS=verbosity=0:log_threads=1 $$i; done'
test: $(TEST_EXE)
@echo test $(TEST_EXE)
@sh -ec 'for i in $(TEST_EXE); do $$i|grep "ctest:name"; done' > result.txt
@ -321,7 +342,7 @@ test: $(TEST_EXE)
EMCC_OPT=-I./include -I./src -Wall -Wextra
EMCC_OPT+=-O3 -DNDEBUG -DMCLSHE_WIN_SIZE=8
EMCC_OPT+=-s WASM=1 -s NO_EXIT_RUNTIME=1 -s MODULARIZE=1 #-s ASSERTIONS=1
EMCC_OPT+=-s WASM=1 -s NO_EXIT_RUNTIME=1 -s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 -s MODULARIZE=1 #-s ASSERTIONS=1
EMCC_OPT+=-DCYBOZU_MINIMUM_EXCEPTION
EMCC_OPT+=-s ABORTING_MALLOC=0
SHE_C_DEP=src/fp.cpp src/she_c_impl.hpp include/mcl/she.hpp include/mcl/fp.hpp include/mcl/op.hpp include/mcl/she.h Makefile
@ -330,37 +351,18 @@ ifeq ($(MCL_USE_LLVM),2)
EMCC_OPT+=src/base64m.ll -DMCL_USE_LLVM
SHE_C_DEP+=src/base64m.ll
endif
../she-wasm/she_c.js: src/she_c256.cpp $(SHE_C_DEP)
emcc -o $@ src/fp.cpp src/she_c256.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=256 -s TOTAL_MEMORY=67108864 -s DISABLE_EXCEPTION_CATCHING=0
../she-wasm/she_c384.js: src/she_c384.cpp $(SHE_C_DEP)
emcc -o $@ src/fp.cpp src/she_c384.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=384 -s TOTAL_MEMORY=67108864 -s DISABLE_EXCEPTION_CATCHING=0
../mcl-wasm/mcl_c.js: src/bn_c256.cpp $(MCL_C_DEP)
emcc -o $@ src/fp.cpp src/bn_c256.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=256 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1 -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -fno-exceptions -MD -MP -MF obj/mcl_c.d
../mcl-wasm/mcl_c512.js: src/bn_c512.cpp $(MCL_C_DEP)
emcc -o $@ src/fp.cpp src/bn_c512.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=512 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1 -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -fno-exceptions
../ecdsa-wasm/ecdsa_c.js: src/ecdsa_c.cpp src/fp.cpp include/mcl/ecdsa.hpp include/mcl/ecdsa.h Makefile
emcc -o $@ src/fp.cpp src/ecdsa_c.cpp $(EMCC_OPT) -DMCL_MAX_BIT_SIZE=256 -DMCL_USE_WEB_CRYPTO_API -s DISABLE_EXCEPTION_CATCHING=1 -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -fno-exceptions
mcl-wasm:
$(MAKE) ../mcl-wasm/mcl_c.js
$(MAKE) ../mcl-wasm/mcl_c512.js
she-wasm:
$(MAKE) ../she-wasm/she_c.js
$(MAKE) ../she-wasm/she_c384.js
ecdsa-wasm:
$(MAKE) ../ecdsa-wasm/ecdsa_c.js
# test
bin/emu:
$(CXX) -g -o $@ src/fp.cpp src/bn_c256.cpp test/bn_c256_test.cpp -DMCL_DONT_USE_XBYAK -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_64BIT_PORTABLE -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=256 -I./include
bin/pairing_c_min.exe: sample/pairing_c.c include/mcl/vint.hpp src/fp.cpp include/mcl/bn.hpp
$(CXX) -o $@ sample/pairing_c.c src/fp.cpp src/bn_c256.cpp -O3 -g -I./include -fno-threadsafe-statics -DMCL_DONT_USE_XBYAK -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=256 -DMCL_VINT_64BIT_PORTABLE -DCYBOZU_DONT_USE_STRING -DCYBOZU_DONT_USE_EXCEPTION -DNDEBUG # -DMCL_DONT_USE_CSPRNG
$(CXX) -std=c++03 -O3 -g -fno-threadsafe-statics -fno-exceptions -fno-rtti -o $@ sample/pairing_c.c src/fp.cpp src/bn_c384_256.cpp -I./include -DXBYAK_NO_EXCEPTION -DMCL_DONT_USE_OPENSSL -DMCL_USE_VINT -DMCL_SIZEOF_UNIT=8 -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=384 -DMCL_VINT_64BIT_PORTABLE -DCYBOZU_DONT_USE_STRING -DCYBOZU_DONT_USE_EXCEPTION -DNDEBUG # -DMCL_DONT_USE_CSPRNG
bin/llvm_test64.exe: test/llvm_test.cpp src/base64.ll
clang++$(LLVM_VER) -o $@ -Ofast -DNDEBUG -Wall -Wextra -I ./include test/llvm_test.cpp src/base64.ll
bin/llvm_test32.exe: test/llvm_test.cpp src/base32.ll
clang++$(LLVM_VER) -o $@ -Ofast -DNDEBUG -Wall -Wextra -I ./include test/llvm_test.cpp src/base32.ll -m32
make_tbl:
$(MAKE) ../bls/src/qcoeff-bn254.hpp
@ -376,7 +378,7 @@ update_cybozulib:
cp -a $(addprefix ../cybozulib/,$(wildcard include/cybozu/*.hpp)) include/cybozu/
clean:
$(RM) $(LIB_DIR)/*.a $(LIB_DIR)/*.$(LIB_SUF) $(OBJ_DIR)/*.o $(OBJ_DIR)/*.obj $(OBJ_DIR)/*.d $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_OBJ) $(LIB_OBJ) $(BN256_OBJ) $(BN384_OBJ) $(BN512_OBJ) $(FUNC_LIST) src/*.ll lib/*.a
$(RM) $(LIB_DIR)/*.a $(LIB_DIR)/*.$(LIB_SUF) $(OBJ_DIR)/*.o $(OBJ_DIR)/*.obj $(OBJ_DIR)/*.d $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_OBJ) $(LIB_OBJ) $(BN256_OBJ) $(BN384_OBJ) $(BN512_OBJ) $(FUNC_LIST) lib/*.a src/static_code.asm src/dump_code
ALL_SRC=$(SRC_SRC) $(TEST_SRC) $(SAMPLE_SRC)
DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC))))
@ -385,12 +387,12 @@ DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC))))
PREFIX?=/usr/local
install: lib/libmcl.a lib/libmcl.$(LIB_SUF)
$(MKDIR) $(PREFIX)/include/mcl
cp -a include/mcl/ $(PREFIX)/include/
cp -a include/cybozu/ $(PREFIX)/include/
cp -a include/mcl $(PREFIX)/include/
cp -a include/cybozu $(PREFIX)/include/
$(MKDIR) $(PREFIX)/lib
cp -a lib/libmcl.a lib/libmcl.$(LIB_SUF) $(PREFIX)/lib/
.PHONY: test mcl-wasm she-wasm bin/emu
.PHONY: test she-wasm bin/emu
# don't remove these files automatically
.SECONDARY: $(addprefix $(OBJ_DIR)/, $(ALL_SRC:.cpp=.o))

548
api.md

@ -0,0 +1,548 @@
# C API
## News
APIs for old ethreum hash functions are removed.
`mclBn_setMapToMode` supports only `MCL_MAP_TO_MODE_ETH2`.
## Minimum sample
[sample/pairing_c.c](sample/pairing_c.c) is a sample of how to use BLS12-381 pairing.
```
cd mcl
make -j4
make bin/pairing_c.exe && bin/pairing_c.exe
```
## Header and libraries
To use BLS12-381, include `mcl/bn_c384_256.h` and link
- libmclbn384_256.{a,so}
- libmcl.{a,so} ; core library
`384_256` means the max bit size of `Fp` is 384 and that size of `Fr` is 256.
## Notation
The elliptic equation of a curve E is `E: y^2 = x^3 + b`.
- `Fp` ; a finite field of a prime order `p`, where curves is defined over.
- `Fr` ; a finite field of a prime order `r`.
- `Fp2` ; the field extension over Fp with degree 2. Fp[i] / (i^2 + 1).
- `Fp6` ; the field extension over Fp2 with degree 3. Fp2[v] / (v^3 - Xi) where Xi = i + 1.
- `Fp12` ; the field extension over Fp6 with degree 2. Fp6[w] / (w^2 - v).
- `G1` ; the cyclic subgroup of E(Fp).
- `G2` ; the cyclic subgroup of the inverse image of E'(Fp^2) under a twisting isomorphism from E' to E.
- `GT` ; the cyclie subgroup of Fp12.
- `G1`, `G2` and `GT` have the order `r`.
The pairing e: G1 x G2 -> GT is the optimal ate pairing.
mcl treats `G1` and `G2` as an additive group and `GT` as a multiplicative group.
- `mclSize` ; `unsigned int` if WebAssembly else `size_t`
### Curve Parameter
r = |G1| = |G2| = |GT|
curveType | b| r and p |
------------|--|------------------|
BN254 | 2|r = 0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d <br> p = 0x2523648240000001ba344d80000000086121000000000013a700000000000013 |
BLS12-381 | 4|r = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 <br> p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab |
BN381 | 2|r = 0x240026400f3d82b2e42de125b00158405b710818ac000007e0042f008e3e00000000001080046200000000000000000d <br> p = 0x240026400f3d82b2e42de125b00158405b710818ac00000840046200950400000000001380052e000000000000000013 |
## Structures
### `mclBnFp`
This is a struct of `Fp`. The value is stored as Montgomery representation.
### `mclBnFr`
This is a struct of `Fr`. The value is stored as Montgomery representation.
### `mclBnFp2`
This is a struct of `Fp2` which has a member `mclBnFp d[2]`.
An element `x` of `Fp2` is represented as `x = d[0] + d[1] i` where `i^2 = -1`.
### `mclBnG1`
This is a struct of `G1` which has three members `x`, `y`, `z` of type `mclBnFp`.
An element `P` of `G1` is represented as `P = [x:y:z]` of a Jacobi coordinate.
### `mclBnG2`
This is a struct of `G2` which has three members `x`, `y`, `z` of type `mclBnFp2`.
An element `Q` of `G2` is represented as `Q = [x:y:z]` of a Jacobi coordinate.
### `mclBnGT`
This is a struct of `GT` which has a member `mclBnFp d[12]`.
### sizeof
library |MCLBN_FR_UNIT_SIZE|MCLBN_FP_UNIT_SIZE|sizeof Fr|sizeof Fp|
------------------|------------------|------------------|---------|---------|
libmclbn256.a | 4 | 4 | 32 | 32 |
libmclbn384_256.a | 4 | 6 | 32 | 48 |
libmclbn384.a | 6 | 6 | 48 | 48 |
## Thread safety
All functions except for initialization and changing global setting are thread-safe.
## Initialization
Initialize mcl library. Call this function at first before calling the other functions.
```
int mclBn_init(int curve, int compiledTimeVar);
```
- `curve` ; specify the curve type
- MCL_BN254 ; BN254 (a little faster if including `mcl/bn_c256.h` and linking `libmclbn256.{a,so}`)
- MCL_BN_SNARK1 ; the same parameter used in libsnark
- MCL_BLS12_381 ; BLS12-381
- MCL_BN381_1 ; BN381 (include `mcl/bn_c384.h` and link `libmclbn384.{a,so}`)
- `compiledTimeVar` ; set `MCLBN_COMPILED_TIME_VAR`, which macro is used to make sure that
the values are the same when the library is built and used.
- return 0 if success.
- This is not thread safe.
## Global setting
```
int mclBn_setMapToMode(int mode);
```
The map-to-G2 function if `mode = MCL_MAP_TO_MODE_HASH_TO_CURVE`.
### Control to verify that a point of the elliptic curve has the order `r`.
This function affects `setStr()` and `deserialize()` for G1/G2.
```
void mclBn_verifyOrderG1(int doVerify);
void mclBn_verifyOrderG2(int doVerify);
```
- verify if `doVerify` is 1 or does not. The default parameter is 0 because the cost of verification is not small.
- Set `doVerify = 1` if considering subgroup attack is necessary.
- This is not thread safe.
## Setter / Getter
### Clear
Set `x` is zero.
```
void mclBnFr_clear(mclBnFr *x);
void mclBnFp_clear(mclBnFp *x);
void mclBnFp2_clear(mclBnFp2 *x);
void mclBnG1_clear(mclBnG1 *x);
void mclBnG2_clear(mclBnG2 *x);
void mclBnGT_clear(mclBnGT *x);
```
### Set `x` to `y`.
```
void mclBnFp_setInt(mclBnFp *y, mclInt x);
void mclBnFr_setInt(mclBnFr *y, mclInt x);
void mclBnGT_setInt(mclBnGT *y, mclInt x);
```
### Set `buf[0..bufSize-1]` to `x` with masking according to the following way.
```
int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize);
int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize);
```
1. set x = buf[0..bufSize-1] as little endian
2. x &= (1 << bitLen(r)) - 1
3. if (x >= r) x &= (1 << (bitLen(r) - 1)) - 1
- always return 0
### Set (`buf[0..bufSize-1]` mod `p` or `r`) to `x`.
```
int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize);
int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize);
```
- return 0 if bufSize <= (sizeof(*x) * 8 * 2) else -1
### Get little endian byte sequence `buf` corresponding to `x`
```
mclSize mclBnFr_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFr *x);
mclSize mclBnFp_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFp *x);
```
- write `x` to `buf` as little endian
- return the written size if sucess else 0
- NOTE: `buf[0] = 0` and return 1 if `x` is zero.
### Serialization
### Serialize
```
mclSize mclBnFr_serialize(void *buf, mclSize maxBufSize, const mclBnFr *x);
mclSize mclBnG1_serialize(void *buf, mclSize maxBufSize, const mclBnG1 *x);
mclSize mclBnG2_serialize(void *buf, mclSize maxBufSize, const mclBnG2 *x);
mclSize mclBnGT_serialize(void *buf, mclSize maxBufSize, const mclBnGT *x);
mclSize mclBnFp_serialize(void *buf, mclSize maxBufSize, const mclBnFp *x);
mclSize mclBnFp2_serialize(void *buf, mclSize maxBufSize, const mclBnFp2 *x);
```
- serialize `x` into `buf[0..maxBufSize-1]`
- return written byte size if success else 0
### Serialization format
- `Fp`(resp. `Fr`) ; a little endian byte sequence with a fixed size
- the size is the return value of `mclBn_getFpByteSize()` (resp. `mclBn_getFpByteSize()`).
- `G1` ; a compressed fixed size
- the size is equal to `mclBn_getG1ByteSize()` (=`mclBn_getFpByteSize()`).
- `G2` ; a compressed fixed size
- the size is equal to `mclBn_getG1ByteSize() * 2`.
pseudo-code to serialize of `P` of `G1` (resp. `G2`)
```
size = mclBn_getG1ByteSize() # resp. mclBn_getG1ByteSize() * 2
if P is zero:
return [0] * size
else:
P = P.normalize()
s = P.x.serialize()
# x in Fp2 is odd <=> x.a is odd
if P.y is odd: # resp. P.y.d[0] is odd
s[byte-length(s) - 1] |= 0x80
return s
```
### Ethereum serialization mode for BLS12-381
```
void mclBn_setETHserialization(int ETHserialization);
```
- serialize according to [serialization of BLS12-381](https://github.com/zkcrypto/pairing/blob/master/src/bls12_381/README.md#serialization) if BLS12-381 is used and `ETHserialization = 1` (default 0).
### Deserialize
```
mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize bufSize);
mclSize mclBnG1_deserialize(mclBnG1 *x, const void *buf, mclSize bufSize);
mclSize mclBnG2_deserialize(mclBnG2 *x, const void *buf, mclSize bufSize);
mclSize mclBnGT_deserialize(mclBnGT *x, const void *buf, mclSize bufSize);
mclSize mclBnFp_deserialize(mclBnFp *x, const void *buf, mclSize bufSize);
mclSize mclBnFp2_deserialize(mclBnFp2 *x, const void *buf, mclSize bufSize);
```
- deserialize `x` from `buf[0..bufSize-1]`
- return read size if success else 0
## String conversion
### Get string
```
mclSize mclBnFr_getStr(char *buf, mclSize maxBufSize, const mclBnFr *x, int ioMode);
mclSize mclBnG1_getStr(char *buf, mclSize maxBufSize, const mclBnG1 *x, int ioMode);
mclSize mclBnG2_getStr(char *buf, mclSize maxBufSize, const mclBnG2 *x, int ioMode);
mclSize mclBnGT_getStr(char *buf, mclSize maxBufSize, const mclBnGT *x, int ioMode);
mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode);
```
- write `x` to `buf` according to `ioMode`
- `ioMode`
- 10 ; decimal number
- 16 ; hexadecimal number
- `MCLBN_IO_EC_PROJ` ; output as Jacobi coordinate
- return `strlen(buf)` if success else 0.
The meaning of the output of `G1`.
- `0` ; infinity
- `1 <x> <y>` ; affine coordinate
- `4 <x> <y> <z>` ; Jacobi coordinate
- the element `<x>` of `G2` outputs `d[0] d[1]`.
### Set string
```
int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnG1_setStr(mclBnG1 *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnG2_setStr(mclBnG2 *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnGT_setStr(mclBnGT *x, const char *buf, mclSize bufSize, int ioMode);
int mclBnFp_setStr(mclBnFp *x, const char *buf, mclSize bufSize, int ioMode);
```
- set `buf[0..bufSize-1]` to `x` accoring to `ioMode`
- return 0 if success else -1
If you want to use the same generators of BLS12-381 with [zkcrypto](https://github.com/zkcrypto/pairing/tree/master/src/bls12_381#g2) then,
```
mclBnG1 P;
mclBnG1_setStr(&P, "1 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569", 10);
mclBnG2 Q;
mclBnG2_setStr(&Q, "1 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582");
```
## Set random value
Set `x` by cryptographically secure pseudo random number generator.
```
int mclBnFr_setByCSPRNG(mclBnFr *x);
int mclBnFp_setByCSPRNG(mclBnFp *x);
```
### Change random generator function
```
void mclBn_setRandFunc(
void *self,
unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize)
);
```
- `self` ; user-defined pointer
- `readFunc` ; user-defined function, which writes random `bufSize` bytes to `buf` and returns `bufSize` if success else returns 0.
- `readFunc` must be thread-safe.
- Set the default random function if `self == 0` and `readFunc == 0`.
- This is not thread safe.
## Arithmetic operations
### neg / inv / sqr / add / sub / mul / div of `Fr`, `Fp`, `Fp2`, `GT`.
```
void mclBnFr_neg(mclBnFr *y, const mclBnFr *x);
void mclBnFr_inv(mclBnFr *y, const mclBnFr *x);
void mclBnFr_sqr(mclBnFr *y, const mclBnFr *x);
void mclBnFr_add(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFr_sub(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFr_mul(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
void mclBnFp_neg(mclBnFp *y, const mclBnFp *x);
void mclBnFp_inv(mclBnFp *y, const mclBnFp *x);
void mclBnFp_sqr(mclBnFp *y, const mclBnFp *x);
void mclBnFp_add(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp_sub(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp_mul(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp_div(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
void mclBnFp2_neg(mclBnFp2 *y, const mclBnFp2 *x);
void mclBnFp2_inv(mclBnFp2 *y, const mclBnFp2 *x);
void mclBnFp2_sqr(mclBnFp2 *y, const mclBnFp2 *x);
void mclBnFp2_add(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnFp2_sub(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnFp2_mul(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnFp2_div(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
void mclBnGT_inv(mclBnGT *y, const mclBnGT *x); // y = a - bw for x = a + bw where Fp12 = Fp6[w]
void mclBnGT_sqr(mclBnGT *y, const mclBnGT *x);
void mclBnGT_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
void mclBnGT_div(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
```
- use `mclBnGT_invGeneric` for an element in Fp12 - GT.
- NOTE: The following functions do NOT return a GT element because GT is multiplicative group.
```
void mclBnGT_neg(mclBnGT *y, const mclBnGT *x);
void mclBnGT_add(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
void mclBnGT_sub(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
```
### Square root of `x`.
```
int mclBnFr_squareRoot(mclBnFr *y, const mclBnFr *x);
int mclBnFp_squareRoot(mclBnFp *y, const mclBnFp *x);
int mclBnFp2_squareRoot(mclBnFp2 *y, const mclBnFp2 *x);
```
- `y` is one of square root of `x` if `y` exists.
- return 0 if success else -1
### add / sub / dbl / neg for `G1` and `G2`.
```
void mclBnG1_neg(mclBnG1 *y, const mclBnG1 *x);
void mclBnG1_dbl(mclBnG1 *y, const mclBnG1 *x);
void mclBnG1_add(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y);
void mclBnG1_sub(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y);
void mclBnG2_neg(mclBnG2 *y, const mclBnG2 *x);
void mclBnG2_dbl(mclBnG2 *y, const mclBnG2 *x);
void mclBnG2_add(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y);
void mclBnG2_sub(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y);
```
### Convert a point from Jacobi coordinate to affine.
```
void mclBnG1_normalize(mclBnG1 *y, const mclBnG1 *x);
void mclBnG2_normalize(mclBnG2 *y, const mclBnG2 *x);
```
- convert `[x:y:z]` to `[x:y:1]` if `z != 0` else `[*:*:0]`
### scalar multiplication
```
void mclBnG1_mul(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y);
void mclBnG2_mul(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y);
void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y);
```
- z = x * y for G1 / G2
- z = pow(x, y) for GT
- use `mclBnGT_powGeneric` for an element in Fp12 - GT.
### multi scalar multiplication
```
void mclBnG1_mulVec(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y, mclSize n);
void mclBnG2_mulVec(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y, mclSize n);
void mclBnGT_powVec(mclBnGT *z, const mclBnGT *x, const mclBnFr *y, mclSize n);
```
- z = sum_{i=0}^{n-1} mul(x[i], y[i]) for G1 / G2.
- z = prod_{i=0}^{n-1} pow(x[i], y[i]) for GT.
## hash and mapTo functions
### Set hash of `buf[0..bufSize-1]` to `x`
```
int mclBnFr_setHashOf(mclBnFr *x, const void *buf, mclSize bufSize);
int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize);
```
- always return 0
- use SHA-256 if sizeof(*x) <= 256 else SHA-512
- set accoring to the same way as `setLittleEndian`
- support the other wasy if you want in the future
### map `x` to G1 / G2.
```
int mclBnFp_mapToG1(mclBnG1 *y, const mclBnFp *x);
int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x);
```
- See `struct MapTo` in `mcl/bn.hpp` for the detail of the algorithm.
- return 0 if success else -1
### hash and map to G1 / G2.
```
int mclBnG1_hashAndMapTo(mclBnG1 *x, const void *buf, mclSize bufSize);
int mclBnG2_hashAndMapTo(mclBnG2 *x, const void *buf, mclSize bufSize);
```
- Combine `setHashOf` and `mapTo` functions
## Pairing operations
The pairing function `e(P, Q)` is consist of two parts:
- `MillerLoop(P, Q)`
- `finalExp(x)`
`finalExp` satisfies the following properties:
- `e(P, Q) = finalExp(MillerLoop(P, Q))`
- `e(P1, Q1) e(P2, Q2) = finalExp(MillerLoop(P1, Q1) MillerLoop(P2, Q2))`
### pairing
```
void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
```
### millerLoop
```
void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
```
### finalExp
```
void mclBn_finalExp(mclBnGT *y, const mclBnGT *x);
```
## Variants of MillerLoop
### multi pairing
```
void mclBn_millerLoopVec(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y, mclSize n);
```
- This function is for multi-pairing
- computes prod_{i=0}^{n-1} MillerLoop(x[i], y[i])
- prod_{i=0}^{n-1} e(x[i], y[i]) = finalExp(prod_{i=0}^{n-1} MillerLoop(x[i], y[i]))
### pairing for a fixed point of G2
```
int mclBn_getUint64NumToPrecompute(void);
void mclBn_precomputeG2(uint64_t *Qbuf, const mclBnG2 *Q);
void mclBn_precomputedMillerLoop(mclBnGT *f, const mclBnG1 *P, const uint64_t *Qbuf);
```
These functions is the same computation of `pairing(P, Q);` as the followings:
```
uint64_t *Qbuf = (uint64_t*)malloc(mclBn_getUint64NumToPrecompute() * sizeof(uint64_t));
mclBn_precomputeG2(Qbuf, Q); // precomputing of Q
mclBn_precomputedMillerLoop(f, P, Qbuf); // pairing of any P of G1 and the fixed Q
free(p);
```
```
void mclBn_precomputedMillerLoop2(
mclBnGT *f,
const mclBnG1 *P1, const uint64_t *Q1buf,
const mclBnG1 *P2, const uint64_t *Q2buf
);
```
- compute `MillerLoop(P1, Q1buf) * MillerLoop(P2, Q2buf)`
```
void mclBn_precomputedMillerLoop2mixed(
mclBnGT *f,
const mclBnG1 *P1, const mclBnG2 *Q1,
const mclBnG1 *P2, const uint64_t *Q2buf
);
```
- compute `MillerLoop(P1, Q2) * MillerLoop(P2, Q2buf)`
## Check value
### Check validness
```
int mclBnFr_isValid(const mclBnFr *x);
int mclBnFp_isValid(const mclBnFp *x);
int mclBnG1_isValid(const mclBnG1 *x);
int mclBnG2_isValid(const mclBnG2 *x);
```
- return 1 if true else 0
### Check the order of a point
```
int mclBnG1_isValidOrder(const mclBnG1 *x);
int mclBnG2_isValidOrder(const mclBnG2 *x);
```
- Check whether the order of `x` is valid or not
- return 1 if true else 0
- This function always cheks according to `mclBn_verifyOrderG1` and `mclBn_verifyOrderG2`.
### Is equal / zero / one / isOdd
```
int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y);
int mclBnFr_isZero(const mclBnFr *x);
int mclBnFr_isOne(const mclBnFr *x);
int mclBnFr_isOdd(const mclBnFr *x);
int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y);
int mclBnFp_isZero(const mclBnFp *x);
int mclBnFp_isOne(const mclBnFp *x);
int mclBnFp_isOdd(const mclBnFp *x);
int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y);
int mclBnFp2_isZero(const mclBnFp2 *x);
int mclBnFp2_isOne(const mclBnFp2 *x);
int mclBnG1_isEqual(const mclBnG1 *x, const mclBnG1 *y);
int mclBnG1_isZero(const mclBnG1 *x);
int mclBnG2_isEqual(const mclBnG2 *x, const mclBnG2 *y);
int mclBnG2_isZero(const mclBnG2 *x);
int mclBnGT_isEqual(const mclBnGT *x, const mclBnGT *y);
int mclBnGT_isZero(const mclBnGT *x);
int mclBnGT_isOne(const mclBnGT *x);
```
- return 1 if true else 0
### isNegative
```
int mclBnFr_isNegative(const mclBnFr *x);
int mclBnFp_isNegative(const mclBnFr *x);
```
return 1 if x >= half where half = (r + 1) / 2 (resp. (p + 1) / 2).
## Lagrange interpolation
```
int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, mclSize k);
int mclBn_G1LagrangeInterpolation(mclBnG1 *out, const mclBnFr *xVec, const mclBnG1 *yVec, mclSize k);
int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVec, const mclBnG2 *yVec, mclSize k);
```
- Lagrange interpolation
- recover out = y(0) from {(xVec[i], yVec[i])} for {i=0..k-1}
- return 0 if success else -1
- satisfy that xVec[i] != 0, xVec[i] != xVec[j] for i != j
```
int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, mclSize cSize, const mclBnFr *x);
int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, mclSize cSize, const mclBnFr *x);
int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, mclSize cSize, const mclBnFr *x);
```
- Evaluate polynomial
- out = f(x) = c[0] + c[1] * x + ... + c[cSize - 1] * x^{cSize - 1}
- return 0 if success else -1
- satisfy cSize >= 1

@ -0,0 +1,67 @@
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
BUILD_DIR=${1:-build}
windows_build()
{
if [ -d "${SCRIPT_DIR}/../cybozulib_ext" ]; then
DOWNLOAD_CYBOZULIB_EXT="OFF"
CYBOZULIB_EXT_OPTION="-DMCL_CYBOZULIB_EXT_DIR:PATH=${SCRIPT_DIR}/../cybozulib_ext"
else
DOWNLOAD_CYBOZULIB_EXT="ON"
CYBOZULIB_EXT_OPTION=""
fi
cmake -E remove_directory ${BUILD_DIR}
cmake -E make_directory ${BUILD_DIR}
cmake -H${SCRIPT_DIR} -B${BUILD_DIR} -A x64 \
-DBUILD_TESTING=ON \
-DMCL_BUILD_SAMPLE=ON \
-DCMAKE_INSTALL_PREFIX=${BUILD_DIR}/install \
-DMCL_DOWNLOAD_SOURCE=${DOWNLOAD_CYBOZULIB_EXT} ${CYBOZULIB_EXT_OPTION}
cmake --build ${BUILD_DIR} --clean-first --config Release --parallel
}
linux_build()
{
cmake -E remove_directory ${BUILD_DIR}
cmake -E make_directory ${BUILD_DIR}
cmake -H${SCRIPT_DIR} -B${BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=ON \
-DMCL_BUILD_SAMPLE=ON \
-DMCL_USE_LLVM=ON \
-DMCL_USE_OPENSSL=ON \
-DCMAKE_INSTALL_PREFIX=${BUILD_DIR}/install
cmake --build ${BUILD_DIR} --clean-first -- -j
}
osx_build()
{
OPENSSL_ROOT_DIR="/usr/local/opt/openssl"
cmake -E remove_directory ${BUILD_DIR}
cmake -E make_directory ${BUILD_DIR}
cmake -H${SCRIPT_DIR} -B${BUILD_DIR} -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=ON \
-DMCL_BUILD_SAMPLE=ON \
-DMCL_USE_LLVM=ON \
-DMCL_USE_OPENSSL=ON \
-DOPENSSL_ROOT_DIR="${OPENSSL_ROOT_DIR}" \
-DCMAKE_INSTALL_PREFIX=${BUILD_DIR}/install
cmake --build ${BUILD_DIR} --clean-first -- -j
}
os=`uname -s`
case "${os}" in
CYGWIN*|MINGW32*|MSYS*|MINGW*)
windows_build
;;
Darwin*)
osx_build
;;
*)
linux_build
;;
esac

@ -0,0 +1,88 @@
# FindGMP.cmake
#
# Finds the GNU Multiple Precision Arithmetic Library (GMP)
# See http://gmplib.org/
#
# This will define the following variables::
#
# GMP_FOUND
# GMP_VERSION
# GMP_DEFINITIONS
# GMP_INCLUDE_DIR
# GMP_LIBRARY
# GMP_GMPXX_DEFINITIONS
# GMP_GMPXX_INCLUDE_DIR
# GMP_GMPXX_LIBRARY
#
# and the following imported targets::
#
# GMP::GMP
# GMP::GMPXX
find_package(PkgConfig QUIET)
pkg_check_modules(PC_GMP QUIET gmp gmpxx)
set(GMP_VERSION ${PC_GMP_gmp_VERSION})
find_library(GMP_LIBRARY
NAMES gmp libgmp
HINTS
${PC_GMP_gmp_LIBDIR}
${PC_GMP_gmp_LIBRARY_DIRS})
find_path(GMP_INCLUDE_DIR
NAMES gmp.h
HINTS
${PC_GMP_gmp_INCLUDEDIR}
${PC_GMP_gmp_INCLUDE_DIRS})
find_library(GMP_GMPXX_LIBRARY
NAMES gmpxx libgmpxx
HINTS
${PC_GMP_gmpxx_LIBDIR}
${PC_GMP_gmpxx_LIBRARY_DIRS})
find_path(GMP_GMPXX_INCLUDE_DIR
NAMES gmpxx.h
HINTS
${PC_GMP_gmpxx_INCLUDEDIR}
${PC_GMP_gmpxx_INCLUDE_DIRS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GMP
REQUIRED_VARS
GMP_INCLUDE_DIR
GMP_LIBRARY
GMP_GMPXX_INCLUDE_DIR
GMP_GMPXX_LIBRARY
VERSION_VAR GMP_VERSION)
if(GMP_FOUND)
set(GMP_LIBRARIES ${GMP_LIBRARY})
set(GMP_INCLUDE_DIRS ${GMP_INCLUDE_DIR})
set(GMP_DEFINITIONS ${PC_GMP_gmp_CFLAGS_OTHER})
set(GMP_GMPXX_LIBRARIES ${GMP_GMPXX_LIBRARY})
set(GMP_GMPXX_INCLUDE_DIRS ${GMP_GMPXX_INCLUDE_DIR})
set(GMP_GMPXX_DEFINITIONS ${PC_GMP_gmpxx_CFLAGS_OTHER})
if(NOT TARGET GMP::GMP)
add_library(GMP::GMP UNKNOWN IMPORTED)
set_target_properties(GMP::GMP PROPERTIES
INTERFACE_COMPILE_OPTIONS "${PC_GMP_gmp_CFLAGS_OTHER}"
INTERFACE_INCLUDE_DIRECTORIES "${GMP_INCLUDE_DIR}"
IMPORTED_LOCATION "${GMP_LIBRARY}")
endif()
if(NOT TARGET GMP::GMPXX)
add_library(GMP::GMPXX UNKNOWN IMPORTED)
set_target_properties(GMP::GMPXX PROPERTIES
INTERFACE_COMPILE_OPTIONS "${PC_GMP_gmpxx_CFLAGS_OTHER}"
INTERFACE_INCLUDE_DIRECTORIES "${GMP_GMPXX_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES GMP::GMP
IMPORTED_LOCATION "${GMP_GMPXX_LIBRARY}")
endif()
endif()
mark_as_advanced(GMP_FOUND GMP_INCLUDE_DIR GMP_LIBRARY)
mark_as_advanced(GMP_GMPXX_INCLUDE_DIR GMP_GMPXX_LIBRARY)

@ -1,29 +1,42 @@
GCC_VER=$(shell $(PRE)$(CC) -dumpversion)
UNAME_S=$(shell uname -s)
ARCH?=$(shell uname -m)
NASM_ELF_OPT=-felf64
ifeq ($(UNAME_S),Linux)
OS=Linux
endif
ifeq ($(findstring MINGW64,$(UNAME_S)),MINGW64)
OS=mingw64
CFLAGS+=-D__USE_MINGW_ANSI_STDIO=1
NASM_ELF_OPT=-fwin64
endif
ifeq ($(findstring CYGWIN,$(UNAME_S)),CYGWIN)
OS=cygwin
endif
ifeq ($(UNAME_S),Darwin)
OS=mac
ARCH=x86_64
ifeq ($(ARCH),x86_64)
OS=mac
else
OS=mac-m1
endif
LIB_SUF=dylib
OPENSSL_DIR?=/usr/local/opt/openssl
CFLAGS+=-I$(OPENSSL_DIR)/include
LDFLAGS+=-L$(OPENSSL_DIR)/lib
GMP_DIR?=/usr/local/opt/gmp
CFLAGS+=-I$(GMP_DIR)/include
LDFLAGS+=-L$(GMP_DIR)/lib
NASM_ELF_OPT=-fmacho64
else
LIB_SUF=so
endif
ARCH?=$(shell uname -m)
ifeq ($(UNAME_S),OpenBSD)
OS=openbsd
CXX?=clang++
CFLAGS+=-I/usr/local/include
LDFLAGS+=-L/usr/local/lib
endif
ifeq ($(UNAME_S),FreeBSD)
OS=freebsd
CXX?=clang++
CFLAGS+=-I/usr/local/include
LDFLAGS+=-L/usr/local/lib
endif
ifneq ($(findstring $(ARCH),x86_64/amd64),)
CPU=x86-64
INTEL=1
@ -42,18 +55,23 @@ ifeq ($(ARCH),x86)
BIT_OPT=-m32
#LOW_ASM_SRC=src/asm/low_x86.asm
endif
ifeq ($(ARCH),armv7l)
ifneq ($(findstring $(ARCH),armv7l/armv6l),)
CPU=arm
BIT=32
#LOW_ASM_SRC=src/asm/low_arm.s
endif
ifeq ($(ARCH),aarch64)
#ifeq ($(ARCH),aarch64)
ifneq ($(findstring $(ARCH),aarch64/arm64),)
CPU=aarch64
BIT=64
endif
ifeq ($(findstring $(OS),mac/mingw64),)
ifeq ($(findstring $(OS),mac/mac-m1/mingw64/openbsd),)
LDFLAGS+=-lrt
endif
ifeq ($(ARCH),s390x)
CPU=systemz
BIT=64
endif
CP=cp -f
AR=ar r
@ -66,12 +84,12 @@ ifeq ($(DEBUG),1)
LDFLAGS+=-fsanitize=address
endif
else
CFLAGS_OPT+=-fomit-frame-pointer -DNDEBUG
CFLAGS_OPT+=-fomit-frame-pointer -DNDEBUG -fno-stack-protector
ifeq ($(CXX),clang++)
CFLAGS_OPT+=-O3
else
ifeq ($(shell expr $(GCC_VER) \> 4.6.0),1)
CFLAGS_OPT+=-Ofast
CFLAGS_OPT+=-O3
else
CFLAGS_OPT+=-O3
endif
@ -84,7 +102,7 @@ else
CFLAGS_OPT+=$(MARCH)
endif
endif
CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith
CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith -Wundef
CFLAGS+=-g3
INC_OPT=-I include -I test
CFLAGS+=$(CFLAGS_WARN) $(BIT_OPT) $(INC_OPT)
@ -95,7 +113,10 @@ CFLAGS+=$(CFLAGS_OPT_USER)
endif
CFLAGS+=$(CFLAGS_USER)
MCL_USE_GMP?=1
MCL_USE_OPENSSL?=1
ifneq ($(OS),mac/mac-m1,)
MCL_USE_GMP=0
endif
MCL_USE_OPENSSL?=0
ifeq ($(MCL_USE_GMP),0)
CFLAGS+=-DMCL_USE_VINT
endif
@ -107,9 +128,24 @@ ifeq ($(MCL_USE_OPENSSL),0)
endif
ifeq ($(MCL_USE_GMP),1)
GMP_LIB=-lgmp -lgmpxx
ifeq ($(UNAME_S),Darwin)
GMP_DIR?=/usr/local/opt/gmp
CFLAGS+=-I$(GMP_DIR)/include
LDFLAGS+=-L$(GMP_DIR)/lib
endif
endif
ifeq ($(MCL_USE_OPENSSL),1)
OPENSSL_LIB=-L${OPENSSL_DIR}/lib -lcrypto
ifeq ($(UNAME_S),Darwin)
OPENSSL_DIR?=/usr/local/opt/openssl
CFLAGS+=-I$(OPENSSL_DIR)/include
LDFLAGS+=-L$(OPENSSL_DIR)/lib
endif
endif
ifeq ($(MCL_STATIC_CODE),1)
MCL_USE_XBYAK=0
MCL_MAX_BIT_SIZE=384
CFLAGS+=-DMCL_STATIC_CODE
endif
LDFLAGS+=$(GMP_LIB) $(OPENSSL_LIB) $(BIT_OPT) $(LDFLAGS_USER)

@ -4,125 +4,126 @@ using System.Runtime.InteropServices;
namespace mcl {
public class BN256 {
[DllImport("mclBn256.dll")]
public const string dllName = "mclBn256";
[DllImport(dllName)]
public static extern int mclBn_init(int curve, int compiledTimeVar);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_clear(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_setInt(ref Fr y, int x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_setStr(ref Fr x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_isValid(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_isEqual(ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_isZero(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_isOne(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_setByCSPRNG(ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_setHashOf(ref Fr x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnFr_getStr([Out]StringBuilder buf, long maxBufSize, ref Fr x, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_neg(ref Fr y, ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_inv(ref Fr y, ref Fr x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_add(ref Fr z, ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_sub(ref Fr z, ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_mul(ref Fr z, ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnFr_div(ref Fr z, ref Fr x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_clear(ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_setStr(ref G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_isValid(ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_isEqual(ref G1 x, ref G1 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_isZero(ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG1_hashAndMapTo(ref G1 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern long mclBnG1_getStr([Out]StringBuilder buf, long maxBufSize, ref G1 x, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_neg(ref G1 y, ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_dbl(ref G1 y, ref G1 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_add(ref G1 z, ref G1 x, ref G1 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_sub(ref G1 z, ref G1 x, ref G1 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG1_mul(ref G1 z, ref G1 x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_clear(ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_setStr(ref G2 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_isValid(ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_isEqual(ref G2 x, ref G2 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_isZero(ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnG2_hashAndMapTo(ref G2 x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern long mclBnG2_getStr([Out]StringBuilder buf, long maxBufSize, ref G2 x, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_neg(ref G2 y, ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_dbl(ref G2 y, ref G2 x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_add(ref G2 z, ref G2 x, ref G2 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_sub(ref G2 z, ref G2 x, ref G2 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnG2_mul(ref G2 z, ref G2 x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_clear(ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnGT_setStr(ref GT x, [In][MarshalAs(UnmanagedType.LPStr)] string buf, long bufSize, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnGT_isEqual(ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnGT_isZero(ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern int mclBnGT_isOne(ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern long mclBnGT_getStr([Out]StringBuilder buf, long maxBufSize, ref GT x, int ioMode);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_neg(ref GT y, ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_inv(ref GT y, ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_add(ref GT z, ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_sub(ref GT z, ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_mul(ref GT z, ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_div(ref GT z, ref GT x, ref GT y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBnGT_pow(ref GT z, ref GT x, ref Fr y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBn_pairing(ref GT z, ref G1 x, ref G2 y);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBn_finalExp(ref GT y, ref GT x);
[DllImport("mclBn256.dll")]
[DllImport(dllName)]
public static extern void mclBn_millerLoop(ref GT z, ref G1 x, ref G2 y);
public static void init()

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30309.148
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "test", "test\test.csproj", "{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "mcl", "mcl\mcl.csproj", "{73288FB5-7173-4AE9-86C6-F76DF219C37B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}.Debug|x64.ActiveCfg = Debug|Any CPU
{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}.Debug|x64.Build.0 = Debug|Any CPU
{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}.Release|x64.ActiveCfg = Release|Any CPU
{31ABF32C-3DAC-47EF-8B99-B531F88B6FDC}.Release|x64.Build.0 = Release|Any CPU
{73288FB5-7173-4AE9-86C6-F76DF219C37B}.Debug|x64.ActiveCfg = Debug|Any CPU
{73288FB5-7173-4AE9-86C6-F76DF219C37B}.Debug|x64.Build.0 = Debug|Any CPU
{73288FB5-7173-4AE9-86C6-F76DF219C37B}.Release|x64.ActiveCfg = Release|Any CPU
{73288FB5-7173-4AE9-86C6-F76DF219C37B}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {ACBC75BC-5FB9-48DF-A78D-7C6BAD21E647}
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load Diff

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="CVS\**" />
<EmbeddedResource Remove="CVS\**" />
<None Remove="CVS\**" />
</ItemGroup>
</Project>

@ -0,0 +1,24 @@
# C# binding of mcl library
# How to build `bin/mclbn384_256.dll`.
```
git clone https://github.com/herumi/mcl
cd mcl
mklib dll
```
Open `mcl/ffi/cs/mcl.sln` and Set the directory of `mcl/bin` to `workingDirectory` at `Debug` of test project.
# Remark
- `bn256.cs` is an old code. It will be removed in the future.
- `mcl/mcl.cs` is a new version. It support `BN254`, `BN_SNARK` and `BLS12_381` curve, which requires `mclbn384_256.dll`.
# `ETHmode` with `BLS12_381`
If you need the map-to-G1/G2 function defined in [Hashing to Elliptic Curves](https://www.ietf.org/id/draft-irtf-cfrg-hash-to-curve-09.html),
then initialize this library as the followings:
```
MCL.Init(BLS12_381);
MCL.ETHmode();
```

@ -0,0 +1,408 @@
using System;
namespace mcl {
using static MCL;
class MCLTest {
static int err = 0;
static void assert(string msg, bool b)
{
if (b) return;
Console.WriteLine("ERR {0}", msg);
err++;
}
static void Main()
{
err = 0;
try {
Console.WriteLine("BN254");
TestCurve(BN254);
Console.WriteLine("BN_SNARK");
TestCurve(BN_SNARK);
Console.WriteLine("BLS12_381");
TestCurve(BLS12_381);
Console.WriteLine("BLS12_381 eth");
ETHmode();
TestETH();
if (err == 0) {
Console.WriteLine("all tests succeed");
} else {
Console.WriteLine("err={0}", err);
}
} catch (Exception e) {
Console.WriteLine("ERR={0}", e);
}
}
static void TestCurve(int curveType)
{
Init(curveType);
TestFr();
TestFp();
TestG1();
TestG2();
TestPairing();
TestSS();
}
static void TestFr()
{
Console.WriteLine("TestFr");
Fr x = new Fr();
assert("x.isZero", x.IsZero());
x.Clear();
assert("0", x.GetStr(10) == "0");
assert("0.IzZero", x.IsZero());
assert("!0.IzOne", !x.IsOne());
x.SetInt(1);
assert("1", x.GetStr(10) == "1");
assert("!1.IzZero", !x.IsZero());
assert("1.IzOne", x.IsOne());
x.SetInt(3);
assert("3", x.GetStr(10) == "3");
assert("!3.IzZero", !x.IsZero());
assert("!3.IzOne", !x.IsOne());
x.SetInt(-5);
x = -x;
assert("5", x.GetStr(10) == "5");
x.SetInt(4);
x = x * x;
assert("16", x.GetStr(10) == "16");
assert("10", x.GetStr(16) == "10");
Fr y;
y = x;
assert("x == y", x.Equals(y));
x.SetInt(123);
assert("123", x.GetStr(10) == "123");
assert("7b", x.GetStr(16) == "7b");
assert("y != x", !x.Equals(y));
Console.WriteLine("exception test");
try {
x.SetStr("1234567891234x", 10);
Console.WriteLine("x = {0}", x);
} catch (Exception e) {
Console.WriteLine("OK ; expected exception: {0}", e);
}
x.SetStr("1234567891234", 10);
assert("1234567891234", x.GetStr(10) == "1234567891234");
{
byte[] buf = x.Serialize();
y.Deserialize(buf);
assert("x == y", x.Equals(y));
}
}
static void TestFp()
{
Console.WriteLine("TestFp");
Fp x = new Fp();
assert("x.isZero", x.IsZero());
x.Clear();
assert("0", x.GetStr(10) == "0");
assert("0.IzZero", x.IsZero());
assert("!0.IzOne", !x.IsOne());
x.SetInt(1);
assert("1", x.GetStr(10) == "1");
assert("!1.IzZero", !x.IsZero());
assert("1.IzOne", x.IsOne());
x.SetInt(3);
assert("3", x.GetStr(10) == "3");
assert("!3.IzZero", !x.IsZero());
assert("!3.IzOne", !x.IsOne());
x.SetInt(-5);
x = -x;
assert("5", x.GetStr(10) == "5");
x.SetInt(4);
x = x * x;
assert("16", x.GetStr(10) == "16");
assert("10", x.GetStr(16) == "10");
Fp y;
y = x;
assert("x == y", x.Equals(y));
x.SetInt(123);
assert("123", x.GetStr(10) == "123");
assert("7b", x.GetStr(16) == "7b");
assert("y != x", !x.Equals(y));
Console.WriteLine("exception test");
try {
x.SetStr("1234567891234x", 10);
Console.WriteLine("x = {0}", x);
} catch (Exception e) {
Console.WriteLine("OK ; expected exception: {0}", e);
}
x.SetStr("1234567891234", 10);
assert("1234567891234", x.GetStr(10) == "1234567891234");
{
byte[] buf = x.Serialize();
y.Deserialize(buf);
assert("x == y", x.Equals(y));
}
}
static void TestG1()
{
Console.WriteLine("TestG1");
G1 P = new G1();
assert("P.isZero", P.IsZero());
P.Clear();
assert("P.IsValid", P.IsValid());
assert("P.IsZero", P.IsZero());
P.HashAndMapTo("abc");
assert("P.IsValid", P.IsValid());
assert("!P.IsZero", !P.IsZero());
G1 Q = new G1();
Q = P;
assert("P == Q", Q.Equals(P));
Q.Neg(P);
Q.Add(Q, P);
assert("P = Q", Q.IsZero());
Q.Dbl(P);
G1 R = new G1();
R.Add(P, P);
assert("Q == R", Q.Equals(R));
Fr x = new Fr();
x.SetInt(3);
R.Add(R, P);
Q.Mul(P, x);
assert("Q == R", Q.Equals(R));
{
byte[] buf = P.Serialize();
Q.Clear();
Q.Deserialize(buf);
assert("P == Q", P.Equals(Q));
}
{
const int n = 5;
G1[] xVec = new G1[n];
Fr[] yVec = new Fr[n];
P.Clear();
for (int i = 0; i < n; i++) {
xVec[i].HashAndMapTo(i.ToString());
yVec[i].SetByCSPRNG();
Q.Mul(xVec[i], yVec[i]);
P.Add(P, Q);
}
MulVec(ref Q, xVec, yVec);
assert("mulVecG1", P.Equals(Q));
}
G1 W = G1.Zero();
assert("W.IsZero", W.IsZero());
}
static void TestG2()
{
Console.WriteLine("TestG2");
G2 P = new G2();
assert("P.isZero", P.IsZero());
P.Clear();
assert("P is valid", P.IsValid());
assert("P is zero", P.IsZero());
P.HashAndMapTo("abc");
assert("P is valid", P.IsValid());
assert("P is not zero", !P.IsZero());
G2 Q = new G2();
Q = P;
assert("P == Q", Q.Equals(P));
Q.Neg(P);
Q.Add(Q, P);
assert("Q is zero", Q.IsZero());
Q.Dbl(P);
G2 R = new G2();
R.Add(P, P);
assert("Q == R", Q.Equals(R));
Fr x = new Fr();
x.SetInt(3);
R.Add(R, P);
Q.Mul(P, x);
assert("Q == R", Q.Equals(R));
{
byte[] buf = P.Serialize();
Q.Clear();
Q.Deserialize(buf);
assert("P == Q", P.Equals(Q));
}
{
const int n = 5;
G2[] xVec = new G2[n];
Fr[] yVec = new Fr[n];
P.Clear();
for (int i = 0; i < n; i++) {
xVec[i].HashAndMapTo(i.ToString());
yVec[i].SetByCSPRNG();
Q.Mul(xVec[i], yVec[i]);
P.Add(P, Q);
}
MulVec(ref Q, xVec, yVec);
assert("mulVecG2", P.Equals(Q));
}
G2 W = G2.Zero();
assert("W.IsZero", W.IsZero());
}
static void TestPairing()
{
Console.WriteLine("TestG2");
G1 P = new G1();
P.HashAndMapTo("123");
G2 Q = new G2();
Q.HashAndMapTo("1");
Fr a = new Fr();
Fr b = new Fr();
a.SetStr("12345678912345673453", 10);
b.SetStr("230498230982394243424", 10);
G1 aP = new G1();
G2 bQ = new G2();
aP.Mul(P, a);
bQ.Mul(Q, b);
GT e1 = new GT();
GT e2 = new GT();
GT e3 = new GT();
e1.Pairing(P, Q);
e2.Pairing(aP, Q);
e3.Pow(e1, a);
assert("e2.Equals(e3)", e2.Equals(e3));
e2.Pairing(P, bQ);
e3.Pow(e1, b);
assert("e2.Equals(e3)", e2.Equals(e3));
}
static void TestETH_mapToG1()
{
var tbl = new[] {
new {
msg = "asdf",
x = "a72df17570d0eb81260042edbea415ad49bdb94a1bc1ce9d1bf147d0d48268170764bb513a3b994d662e1faba137106",
y = "122b77eca1ed58795b7cd456576362f4f7bd7a572a29334b4817898a42414d31e9c0267f2dc481a4daf8bcf4a460322",
},
};
G1 P = new G1();
Fp x = new Fp();
Fp y = new Fp();
foreach (var v in tbl) {
P.HashAndMapTo(v.msg);
x.SetStr(v.x, 16);
y.SetStr(v.y, 16);
Normalize(ref P, P);
Console.WriteLine("x={0}", P.x.GetStr(16));
Console.WriteLine("y={0}", P.y.GetStr(16));
assert("P.x", P.x.Equals(x));
assert("P.y", P.y.Equals(y));
}
}
static void TestETH()
{
TestETH_mapToG1();
}
static void TestSS_Fr()
{
const int n = 5;
const int k = 3; // can't change because the following loop
Fr[] cVec = new Fr[k];
// init polynomial coefficient
for (int i = 0; i < k; i++) {
cVec[i].SetByCSPRNG();
}
Fr[] xVec = new Fr[n];
Fr[] yVec = new Fr[n];
// share cVec[0] with yVec[0], ..., yVec[n-1]
for (int i = 0; i < n; i++) {
xVec[i].SetHashOf(i.ToString());
MCL.Share(ref yVec[i], cVec, xVec[i]);
}
// recover cVec[0] from xVecSubset and yVecSubset
Fr[] xVecSubset = new Fr[k];
Fr[] yVecSubset = new Fr[k];
for (int i0 = 0; i0 < n; i0++) {
xVecSubset[0] = xVec[i0];
yVecSubset[0] = yVec[i0];
for (int i1 = i0 + 1; i1 < n; i1++) {
xVecSubset[1] = xVec[i1];
yVecSubset[1] = yVec[i1];
for (int i2 = i1 + 1; i2 < n; i2++) {
xVecSubset[2] = xVec[i2];
yVecSubset[2] = yVec[i2];
Fr s = new Fr();
MCL.Recover(ref s, xVecSubset, yVecSubset);
assert("Recover", s.Equals(cVec[0]));
}
}
}
}
static void TestSS_G1()
{
const int n = 5;
const int k = 3; // can't change because the following loop
G1[] cVec = new G1[k];
// init polynomial coefficient
for (int i = 0; i < k; i++) {
Fr x = new Fr();
x.SetByCSPRNG();
cVec[i].SetHashOf(x.GetStr(16));
}
Fr[] xVec = new Fr[n];
G1[] yVec = new G1[n];
// share cVec[0] with yVec[0], ..., yVec[n-1]
for (int i = 0; i < n; i++) {
xVec[i].SetHashOf(i.ToString());
MCL.Share(ref yVec[i], cVec, xVec[i]);
}
// recover cVec[0] from xVecSubset and yVecSubset
Fr[] xVecSubset = new Fr[k];
G1[] yVecSubset = new G1[k];
for (int i0 = 0; i0 < n; i0++) {
xVecSubset[0] = xVec[i0];
yVecSubset[0] = yVec[i0];
for (int i1 = i0 + 1; i1 < n; i1++) {
xVecSubset[1] = xVec[i1];
yVecSubset[1] = yVec[i1];
for (int i2 = i1 + 1; i2 < n; i2++) {
xVecSubset[2] = xVec[i2];
yVecSubset[2] = yVec[i2];
G1 s = new G1();
MCL.Recover(ref s, xVecSubset, yVecSubset);
assert("Recover", s.Equals(cVec[0]));
}
}
}
}
static void TestSS_G2()
{
const int n = 5;
const int k = 3; // can't change because the following loop
G2[] cVec = new G2[k];
// init polynomial coefficient
for (int i = 0; i < k; i++) {
Fr x = new Fr();
x.SetByCSPRNG();
cVec[i].SetHashOf(x.GetStr(16));
}
Fr[] xVec = new Fr[n];
G2[] yVec = new G2[n];
// share cVec[0] with yVec[0], ..., yVec[n-1]
for (int i = 0; i < n; i++) {
xVec[i].SetHashOf(i.ToString());
MCL.Share(ref yVec[i], cVec, xVec[i]);
}
// recover cVec[0] from xVecSubset and yVecSubset
Fr[] xVecSubset = new Fr[k];
G2[] yVecSubset = new G2[k];
for (int i0 = 0; i0 < n; i0++) {
xVecSubset[0] = xVec[i0];
yVecSubset[0] = yVec[i0];
for (int i1 = i0 + 1; i1 < n; i1++) {
xVecSubset[1] = xVec[i1];
yVecSubset[1] = yVec[i1];
for (int i2 = i1 + 1; i2 < n; i2++) {
xVecSubset[2] = xVec[i2];
yVecSubset[2] = yVec[i2];
G2 s = new G2();
MCL.Recover(ref s, xVecSubset, yVecSubset);
assert("Recover", s.Equals(cVec[0]));
}
}
}
}
static void TestSS()
{
TestSS_Fr();
TestSS_G1();
TestSS_G2();
}
}
}

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<Compile Remove="CVS\**" />
<EmbeddedResource Remove="CVS\**" />
<None Remove="CVS\**" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\mcl\mcl.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath></OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath></OutputPath>
</PropertyGroup>
</Project>

@ -11,6 +11,7 @@ package mcl
*/
import "C"
import "fmt"
// Init --
// call this function before calling all the other operations
// this function is not thread safe
@ -21,5 +22,3 @@ func Init(curve int) error {
}
return nil
}

@ -19,18 +19,27 @@ const CurveFp382_1 = C.mclBn_CurveFp382_1
// CurveFp382_2 -- 382 bit curve 2
const CurveFp382_2 = C.mclBn_CurveFp382_2
// BLS12_381
// BLS12_381 --
const BLS12_381 = C.MCL_BLS12_381
// IoSerializeHexStr
// IoSerializeHexStr --
const IoSerializeHexStr = C.MCLBN_IO_SERIALIZE_HEX_STR
// GetFrUnitSize() --
// IO_EC_AFFINE --
const IO_EC_AFFINE = C.MCLBN_IO_EC_AFFINE
// IO_EC_PROJ --
const IO_EC_PROJ = C.MCLBN_IO_EC_PROJ
// IRTF -- for SetMapToMode
const IRTF = 5 /* MCL_MAP_TO_MODE_HASH_TO_CURVE_07 */
// GetFrUnitSize --
func GetFrUnitSize() int {
return int(C.MCLBN_FR_UNIT_SIZE)
}
// GetFpUnitSize() --
// GetFpUnitSize --
// same as GetMaxOpUnitSize()
func GetFpUnitSize() int {
return int(C.MCLBN_FP_UNIT_SIZE)
@ -47,6 +56,34 @@ func GetOpUnitSize() int {
return int(C.mclBn_getOpUnitSize())
}
// GetFrByteSize -- the serialized size of Fr
func GetFrByteSize() int {
return int(C.mclBn_getFrByteSize())
}
// GetFpByteSize -- the serialized size of Fp
func GetFpByteSize() int {
return int(C.mclBn_getFpByteSize())
}
// GetG1ByteSize -- the serialized size of G1
func GetG1ByteSize() int {
return GetFpByteSize()
}
// GetG2ByteSize -- the serialized size of G2
func GetG2ByteSize() int {
return GetFpByteSize() * 2
}
// allow zero length byte
func getPointer(msg []byte) unsafe.Pointer {
if len(msg) == 0 {
return nil
}
return unsafe.Pointer(&msg[0])
}
// GetCurveOrder --
// return the order of G1
func GetCurveOrder() string {
@ -71,6 +108,42 @@ func GetFieldOrder() string {
return string(buf[:n])
}
func bool2Cint(b bool) C.int {
if b {
return 1
} else {
return 0
}
}
// VerifyOrderG1 -- verify order if SetString/Deserialize are called
func VerifyOrderG1(doVerify bool) {
// #nosec
C.mclBn_verifyOrderG1(bool2Cint(doVerify))
}
// VerifyOrderG2 -- verify order if SetString/Deserialize are called
func VerifyOrderG2(doVerify bool) {
// #nosec
C.mclBn_verifyOrderG2(bool2Cint(doVerify))
}
// SetETHserialization --
func SetETHserialization(enable bool) {
// #nosec
C.mclBn_setETHserialization(bool2Cint(enable))
}
// SetMapToMode --
func SetMapToMode(mode int) error {
// #nosec
err := C.mclBn_setMapToMode((C.int)(mode))
if err != 0 {
return fmt.Errorf("SetMapToMode mode=%d\n", mode)
}
return nil
}
// Fr --
type Fr struct {
v C.mclBnFr
@ -98,7 +171,7 @@ func (x *Fr) SetInt64(v int64) {
func (x *Fr) SetString(s string, base int) error {
buf := []byte(s)
// #nosec
err := C.mclBnFr_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base))
err := C.mclBnFr_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base))
if err != 0 {
return fmt.Errorf("err mclBnFr_setStr %x", err)
}
@ -108,8 +181,8 @@ func (x *Fr) SetString(s string, base int) error {
// Deserialize --
func (x *Fr) Deserialize(buf []byte) error {
// #nosec
err := C.mclBnFr_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if err == 0 {
n := C.mclBnFr_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnFr_deserialize %x", buf)
}
return nil
@ -118,13 +191,33 @@ func (x *Fr) Deserialize(buf []byte) error {
// SetLittleEndian --
func (x *Fr) SetLittleEndian(buf []byte) error {
// #nosec
err := C.mclBnFr_setLittleEndian(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
err := C.mclBnFr_setLittleEndian(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFr_setLittleEndian %x", err)
}
return nil
}
// SetLittleEndianMod --
func (x *Fr) SetLittleEndianMod(buf []byte) error {
// #nosec
err := C.mclBnFr_setLittleEndianMod(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFr_setLittleEndianMod %x", err)
}
return nil
}
// SetBigEndianMod --
func (x *Fr) SetBigEndianMod(buf []byte) error {
// #nosec
err := C.mclBnFr_setBigEndianMod(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFr_setBigEndianMod %x", err)
}
return nil
}
// IsEqual --
func (x *Fr) IsEqual(rhs *Fr) bool {
return C.mclBnFr_isEqual(x.getPointer(), rhs.getPointer()) == 1
@ -135,11 +228,26 @@ func (x *Fr) IsZero() bool {
return C.mclBnFr_isZero(x.getPointer()) == 1
}
// IsValid --
func (x *Fr) IsValid() bool {
return C.mclBnFr_isValid(x.getPointer()) == 1
}
// IsOne --
func (x *Fr) IsOne() bool {
return C.mclBnFr_isOne(x.getPointer()) == 1
}
// IsOdd --
func (x *Fr) IsOdd() bool {
return C.mclBnFr_isOdd(x.getPointer()) == 1
}
// IsNegative -- true if x >= (r + 1) / 2
func (x *Fr) IsNegative() bool {
return C.mclBnFr_isNegative(x.getPointer()) == 1
}
// SetByCSPRNG --
func (x *Fr) SetByCSPRNG() {
err := C.mclBnFr_setByCSPRNG(x.getPointer())
@ -151,7 +259,7 @@ func (x *Fr) SetByCSPRNG() {
// SetHashOf --
func (x *Fr) SetHashOf(buf []byte) bool {
// #nosec
return C.mclBnFr_setHashOf(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) == 0
return C.mclBnFr_setHashOf(x.getPointer(), getPointer(buf), C.size_t(len(buf))) == 0
}
// GetString --
@ -186,6 +294,11 @@ func FrInv(out *Fr, x *Fr) {
C.mclBnFr_inv(out.getPointer(), x.getPointer())
}
// FrSqr --
func FrSqr(out *Fr, x *Fr) {
C.mclBnFr_sqr(out.getPointer(), x.getPointer())
}
// FrAdd --
func FrAdd(out *Fr, x *Fr, y *Fr) {
C.mclBnFr_add(out.getPointer(), x.getPointer(), y.getPointer())
@ -206,9 +319,289 @@ func FrDiv(out *Fr, x *Fr, y *Fr) {
C.mclBnFr_div(out.getPointer(), x.getPointer(), y.getPointer())
}
// FrSquareRoot --
func FrSquareRoot(out *Fr, x *Fr) bool {
return C.mclBnFr_squareRoot(out.getPointer(), x.getPointer()) == 0
}
// Fp --
type Fp struct {
v C.mclBnFp
}
// getPointer --
func (x *Fp) getPointer() (p *C.mclBnFp) {
// #nosec
return (*C.mclBnFp)(unsafe.Pointer(x))
}
// Clear --
func (x *Fp) Clear() {
// #nosec
C.mclBnFp_clear(x.getPointer())
}
// SetInt64 --
func (x *Fp) SetInt64(v int64) {
// #nosec
C.mclBnFp_setInt(x.getPointer(), C.int64_t(v))
}
// SetString --
func (x *Fp) SetString(s string, base int) error {
buf := []byte(s)
// #nosec
err := C.mclBnFp_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base))
if err != 0 {
return fmt.Errorf("err mclBnFp_setStr %x", err)
}
return nil
}
// Deserialize --
func (x *Fp) Deserialize(buf []byte) error {
// #nosec
n := C.mclBnFp_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnFp_deserialize %x", buf)
}
return nil
}
// SetLittleEndian --
func (x *Fp) SetLittleEndian(buf []byte) error {
// #nosec
err := C.mclBnFp_setLittleEndian(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFp_setLittleEndian %x", err)
}
return nil
}
// SetLittleEndianMod --
func (x *Fp) SetLittleEndianMod(buf []byte) error {
// #nosec
err := C.mclBnFp_setLittleEndianMod(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFp_setLittleEndianMod %x", err)
}
return nil
}
// SetBigEndianMod --
func (x *Fp) SetBigEndianMod(buf []byte) error {
// #nosec
err := C.mclBnFp_setBigEndianMod(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnFp_setBigEndianMod %x", err)
}
return nil
}
// IsEqual --
func (x *Fp) IsEqual(rhs *Fp) bool {
return C.mclBnFp_isEqual(x.getPointer(), rhs.getPointer()) == 1
}
// IsZero --
func (x *Fp) IsZero() bool {
return C.mclBnFp_isZero(x.getPointer()) == 1
}
// IsValid --
func (x *Fp) IsValid() bool {
return C.mclBnFp_isValid(x.getPointer()) == 1
}
// IsOne --
func (x *Fp) IsOne() bool {
return C.mclBnFp_isOne(x.getPointer()) == 1
}
// IsOdd --
func (x *Fp) IsOdd() bool {
return C.mclBnFp_isOdd(x.getPointer()) == 1
}
// IsNegative -- true if x >= (p + 1) / 2
func (x *Fp) IsNegative() bool {
return C.mclBnFp_isNegative(x.getPointer()) == 1
}
// SetByCSPRNG --
func (x *Fp) SetByCSPRNG() {
err := C.mclBnFp_setByCSPRNG(x.getPointer())
if err != 0 {
panic("err mclBnFp_setByCSPRNG")
}
}
// SetHashOf --
func (x *Fp) SetHashOf(buf []byte) bool {
// #nosec
return C.mclBnFp_setHashOf(x.getPointer(), getPointer(buf), C.size_t(len(buf))) == 0
}
// GetString --
func (x *Fp) GetString(base int) string {
buf := make([]byte, 2048)
// #nosec
n := C.mclBnFp_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base))
if n == 0 {
panic("err mclBnFp_getStr")
}
return string(buf[:n])
}
// Serialize --
func (x *Fp) Serialize() []byte {
buf := make([]byte, 2048)
// #nosec
n := C.mclBnFp_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
if n == 0 {
panic("err mclBnFp_serialize")
}
return buf[:n]
}
// FpNeg --
func FpNeg(out *Fp, x *Fp) {
C.mclBnFp_neg(out.getPointer(), x.getPointer())
}
// FpInv --
func FpInv(out *Fp, x *Fp) {
C.mclBnFp_inv(out.getPointer(), x.getPointer())
}
// FpSqr --
func FpSqr(out *Fp, x *Fp) {
C.mclBnFp_sqr(out.getPointer(), x.getPointer())
}
// FpAdd --
func FpAdd(out *Fp, x *Fp, y *Fp) {
C.mclBnFp_add(out.getPointer(), x.getPointer(), y.getPointer())
}
// FpSub --
func FpSub(out *Fp, x *Fp, y *Fp) {
C.mclBnFp_sub(out.getPointer(), x.getPointer(), y.getPointer())
}
// FpMul --
func FpMul(out *Fp, x *Fp, y *Fp) {
C.mclBnFp_mul(out.getPointer(), x.getPointer(), y.getPointer())
}
// FpDiv --
func FpDiv(out *Fp, x *Fp, y *Fp) {
C.mclBnFp_div(out.getPointer(), x.getPointer(), y.getPointer())
}
// FpSquareRoot --
func FpSquareRoot(out *Fp, x *Fp) bool {
return C.mclBnFp_squareRoot(out.getPointer(), x.getPointer()) == 0
}
// Fp2 -- x = D[0] + D[1] i where i^2 = -1
type Fp2 struct {
D [2]Fp
}
// getPointer --
func (x *Fp2) getPointer() (p *C.mclBnFp2) {
// #nosec
return (*C.mclBnFp2)(unsafe.Pointer(x))
}
// Clear --
func (x *Fp2) Clear() {
// #nosec
C.mclBnFp2_clear(x.getPointer())
}
// Deserialize --
func (x *Fp2) Deserialize(buf []byte) error {
// #nosec
n := C.mclBnFp2_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnFp2_deserialize %x", buf)
}
return nil
}
// IsEqual --
func (x *Fp2) IsEqual(rhs *Fp2) bool {
return C.mclBnFp2_isEqual(x.getPointer(), rhs.getPointer()) == 1
}
// IsZero --
func (x *Fp2) IsZero() bool {
return C.mclBnFp2_isZero(x.getPointer()) == 1
}
// IsOne --
func (x *Fp2) IsOne() bool {
return C.mclBnFp2_isOne(x.getPointer()) == 1
}
// Serialize --
func (x *Fp2) Serialize() []byte {
buf := make([]byte, 2048)
// #nosec
n := C.mclBnFp2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
if n == 0 {
panic("err mclBnFp2_serialize")
}
return buf[:n]
}
// Fp2Neg --
func Fp2Neg(out *Fp2, x *Fp2) {
C.mclBnFp2_neg(out.getPointer(), x.getPointer())
}
// Fp2Inv --
func Fp2Inv(out *Fp2, x *Fp2) {
C.mclBnFp2_inv(out.getPointer(), x.getPointer())
}
// Fp2Sqr --
func Fp2Sqr(out *Fp2, x *Fp2) {
C.mclBnFp2_sqr(out.getPointer(), x.getPointer())
}
// Fp2Add --
func Fp2Add(out *Fp2, x *Fp2, y *Fp2) {
C.mclBnFp2_add(out.getPointer(), x.getPointer(), y.getPointer())
}
// Fp2Sub --
func Fp2Sub(out *Fp2, x *Fp2, y *Fp2) {
C.mclBnFp2_sub(out.getPointer(), x.getPointer(), y.getPointer())
}
// Fp2Mul --
func Fp2Mul(out *Fp2, x *Fp2, y *Fp2) {
C.mclBnFp2_mul(out.getPointer(), x.getPointer(), y.getPointer())
}
// Fp2Div --
func Fp2Div(out *Fp2, x *Fp2, y *Fp2) {
C.mclBnFp2_div(out.getPointer(), x.getPointer(), y.getPointer())
}
// Fp2SquareRoot --
func Fp2SquareRoot(out *Fp2, x *Fp2) bool {
return C.mclBnFp2_squareRoot(out.getPointer(), x.getPointer()) == 0
}
// G1 --
type G1 struct {
v C.mclBnG1
X Fp
Y Fp
Z Fp
}
// getPointer --
@ -227,7 +620,7 @@ func (x *G1) Clear() {
func (x *G1) SetString(s string, base int) error {
buf := []byte(s)
// #nosec
err := C.mclBnG1_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base))
err := C.mclBnG1_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base))
if err != 0 {
return fmt.Errorf("err mclBnG1_setStr %x", err)
}
@ -237,13 +630,54 @@ func (x *G1) SetString(s string, base int) error {
// Deserialize --
func (x *G1) Deserialize(buf []byte) error {
// #nosec
err := C.mclBnG1_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if err == 0 {
n := C.mclBnG1_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnG1_deserialize %x", buf)
}
return nil
}
const ZERO_HEADER = 1 << 6
func isZeroFormat(buf []byte, n int) bool {
if len(buf) < n {
return false
}
if buf[0] != ZERO_HEADER {
return false
}
for i := 1; i < n; i++ {
if buf[i] != 0 {
return false
}
}
return true
}
// DeserializeUncompressed -- x.Deserialize() + y.Deserialize()
func (x *G1) DeserializeUncompressed(buf []byte) error {
if isZeroFormat(buf, GetG1ByteSize()*2) {
x.Clear()
return nil
}
// #nosec
var n = C.mclBnFp_deserialize(x.X.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 {
return fmt.Errorf("err UncompressedDeserialize X %x", buf)
}
buf = buf[n:]
// #nosec
n = C.mclBnFp_deserialize(x.Y.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 {
return fmt.Errorf("err UncompressedDeserialize Y %x", buf)
}
x.Z.SetInt64(1)
if !x.IsValid() {
return fmt.Errorf("err invalid point")
}
return nil
}
// IsEqual --
func (x *G1) IsEqual(rhs *G1) bool {
return C.mclBnG1_isEqual(x.getPointer(), rhs.getPointer()) == 1
@ -254,10 +688,20 @@ func (x *G1) IsZero() bool {
return C.mclBnG1_isZero(x.getPointer()) == 1
}
// IsValid --
func (x *G1) IsValid() bool {
return C.mclBnG1_isValid(x.getPointer()) == 1
}
// IsValidOrder --
func (x *G1) IsValidOrder() bool {
return C.mclBnG1_isValidOrder(x.getPointer()) == 1
}
// HashAndMapTo --
func (x *G1) HashAndMapTo(buf []byte) error {
// #nosec
err := C.mclBnG1_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
err := C.mclBnG1_hashAndMapTo(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnG1_hashAndMapTo %x", err)
}
@ -277,13 +721,39 @@ func (x *G1) GetString(base int) string {
// Serialize --
func (x *G1) Serialize() []byte {
buf := make([]byte, 2048)
buf := make([]byte, GetG1ByteSize())
// #nosec
n := C.mclBnG1_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer())
if n == 0 {
panic("err mclBnG1_serialize")
}
return buf[:n]
return buf
}
// SerializeUncompressed -- all zero array if x.IsZero()
func (x *G1) SerializeUncompressed() []byte {
buf := make([]byte, GetG1ByteSize()*2)
if x.IsZero() {
buf[0] = ZERO_HEADER
return buf
}
var nx G1
G1Normalize(&nx, x)
// #nosec
var n = C.mclBnFp_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), nx.X.getPointer())
if n == 0 {
panic("err mclBnFp_serialize X")
}
n = C.mclBnFp_serialize(unsafe.Pointer(&buf[n]), C.size_t(len(buf))-n, nx.Y.getPointer())
if n == 0 {
panic("err mclBnFp_serialize Y")
}
return buf
}
// G1Normalize --
func G1Normalize(out *G1, x *G1) {
C.mclBnG1_normalize(out.getPointer(), x.getPointer())
}
// G1Neg --
@ -311,6 +781,19 @@ func G1Mul(out *G1, x *G1, y *Fr) {
C.mclBnG1_mul(out.getPointer(), x.getPointer(), y.getPointer())
}
// G1MulVec -- multi scalar multiplication out = sum mul(xVec[i], yVec[i])
func G1MulVec(out *G1, xVec []G1, yVec []Fr) {
n := len(xVec)
if n != len(yVec) {
panic("xVec and yVec have the same size")
}
if n == 0 {
out.Clear()
return
}
C.mclBnG1_mulVec(out.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
}
// G1MulCT -- constant time (depending on bit lengh of y)
func G1MulCT(out *G1, x *G1, y *Fr) {
C.mclBnG1_mulCT(out.getPointer(), x.getPointer(), y.getPointer())
@ -318,7 +801,9 @@ func G1MulCT(out *G1, x *G1, y *Fr) {
// G2 --
type G2 struct {
v C.mclBnG2
X Fp2
Y Fp2
Z Fp2
}
// getPointer --
@ -337,7 +822,7 @@ func (x *G2) Clear() {
func (x *G2) SetString(s string, base int) error {
buf := []byte(s)
// #nosec
err := C.mclBnG2_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base))
err := C.mclBnG2_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base))
if err != 0 {
return fmt.Errorf("err mclBnG2_setStr %x", err)
}
@ -347,13 +832,38 @@ func (x *G2) SetString(s string, base int) error {
// Deserialize --
func (x *G2) Deserialize(buf []byte) error {
// #nosec
err := C.mclBnG2_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if err == 0 {
n := C.mclBnG2_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnG2_deserialize %x", buf)
}
return nil
}
// DeserializeUncompressed -- x.Deserialize() + y.Deserialize()
func (x *G2) DeserializeUncompressed(buf []byte) error {
if isZeroFormat(buf, GetG2ByteSize()*2) {
x.Clear()
return nil
}
// #nosec
var n = C.mclBnFp2_deserialize(x.X.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 {
return fmt.Errorf("err UncompressedDeserialize X %x", buf)
}
buf = buf[n:]
// #nosec
n = C.mclBnFp2_deserialize(x.Y.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 {
return fmt.Errorf("err UncompressedDeserialize Y %x", buf)
}
x.Z.D[0].SetInt64(1)
x.Z.D[1].Clear()
if !x.IsValid() {
return fmt.Errorf("err invalid point")
}
return nil
}
// IsEqual --
func (x *G2) IsEqual(rhs *G2) bool {
return C.mclBnG2_isEqual(x.getPointer(), rhs.getPointer()) == 1
@ -364,10 +874,20 @@ func (x *G2) IsZero() bool {
return C.mclBnG2_isZero(x.getPointer()) == 1
}
// IsValid --
func (x *G2) IsValid() bool {
return C.mclBnG2_isValid(x.getPointer()) == 1
}
// IsValidOrder --
func (x *G2) IsValidOrder() bool {
return C.mclBnG2_isValidOrder(x.getPointer()) == 1
}
// HashAndMapTo --
func (x *G2) HashAndMapTo(buf []byte) error {
// #nosec
err := C.mclBnG2_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
err := C.mclBnG2_hashAndMapTo(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if err != 0 {
return fmt.Errorf("err mclBnG2_hashAndMapTo %x", err)
}
@ -396,6 +916,32 @@ func (x *G2) Serialize() []byte {
return buf[:n]
}
// SerializeUncompressed -- all zero array if x.IsZero()
func (x *G2) SerializeUncompressed() []byte {
buf := make([]byte, GetG2ByteSize()*2)
if x.IsZero() {
buf[0] = ZERO_HEADER
return buf
}
var nx G2
G2Normalize(&nx, x)
// #nosec
var n = C.mclBnFp2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), nx.X.getPointer())
if n == 0 {
panic("err mclBnFp2_serialize X")
}
n = C.mclBnFp2_serialize(unsafe.Pointer(&buf[n]), C.size_t(len(buf))-n, nx.Y.getPointer())
if n == 0 {
panic("err mclBnFp2_serialize Y")
}
return buf
}
// G2Normalize --
func G2Normalize(out *G2, x *G2) {
C.mclBnG2_normalize(out.getPointer(), x.getPointer())
}
// G2Neg --
func G2Neg(out *G2, x *G2) {
C.mclBnG2_neg(out.getPointer(), x.getPointer())
@ -421,6 +967,19 @@ func G2Mul(out *G2, x *G2, y *Fr) {
C.mclBnG2_mul(out.getPointer(), x.getPointer(), y.getPointer())
}
// G2MulVec -- multi scalar multiplication out = sum mul(xVec[i], yVec[i])
func G2MulVec(out *G2, xVec []G2, yVec []Fr) {
n := len(xVec)
if n != len(yVec) {
panic("xVec and yVec have the same size")
}
if n == 0 {
out.Clear()
return
}
C.mclBnG2_mulVec(out.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
}
// GT --
type GT struct {
v C.mclBnGT
@ -448,7 +1007,7 @@ func (x *GT) SetInt64(v int64) {
func (x *GT) SetString(s string, base int) error {
buf := []byte(s)
// #nosec
err := C.mclBnGT_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base))
err := C.mclBnGT_setStr(x.getPointer(), (*C.char)(getPointer(buf)), C.size_t(len(buf)), C.int(base))
if err != 0 {
return fmt.Errorf("err mclBnGT_setStr %x", err)
}
@ -458,8 +1017,8 @@ func (x *GT) SetString(s string, base int) error {
// Deserialize --
func (x *GT) Deserialize(buf []byte) error {
// #nosec
err := C.mclBnGT_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
if err == 0 {
n := C.mclBnGT_deserialize(x.getPointer(), getPointer(buf), C.size_t(len(buf)))
if n == 0 || int(n) != len(buf) {
return fmt.Errorf("err mclBnGT_deserialize %x", buf)
}
return nil
@ -537,6 +1096,22 @@ func GTPow(out *GT, x *GT, y *Fr) {
C.mclBnGT_pow(out.getPointer(), x.getPointer(), y.getPointer())
}
// MapToG1 --
func MapToG1(out *G1, x *Fp) error {
if C.mclBnFp_mapToG1(out.getPointer(), x.getPointer()) != 0 {
return fmt.Errorf("err mclBnFp_mapToG1")
}
return nil
}
// MapToG2 --
func MapToG2(out *G2, x *Fp2) error {
if C.mclBnFp2_mapToG2(out.getPointer(), x.getPointer()) != 0 {
return fmt.Errorf("err mclBnFp2_mapToG2")
}
return nil
}
// Pairing --
func Pairing(out *GT, x *G1, y *G2) {
C.mclBn_pairing(out.getPointer(), x.getPointer(), y.getPointer())
@ -552,6 +1127,19 @@ func MillerLoop(out *GT, x *G1, y *G2) {
C.mclBn_millerLoop(out.getPointer(), x.getPointer(), y.getPointer())
}
// MillerLoopVec -- multi pairings ; out = prod_i e(xVec[i], yVec[i])
func MillerLoopVec(out *GT, xVec []G1, yVec []G2) {
n := len(xVec)
if n != len(yVec) {
panic("xVec and yVec have the same size")
}
if n == 0 {
out.SetInt64(1)
return
}
C.mclBn_millerLoopVec(out.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
}
// GetUint64NumToPrecompute --
func GetUint64NumToPrecompute() int {
return int(C.mclBn_getUint64NumToPrecompute())
@ -577,8 +1165,13 @@ func PrecomputedMillerLoop2(out *GT, P1 *G1, Q1buf []uint64, P2 *G1, Q2buf []uin
// FrEvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ...
func FrEvaluatePolynomial(y *Fr, c []Fr, x *Fr) error {
n := len(c)
if n == 0 {
y.Clear()
return nil
}
// #nosec
err := C.mclBn_FrEvaluatePolynomial(y.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer())
err := C.mclBn_FrEvaluatePolynomial(y.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&c[0])), (C.size_t)(n), x.getPointer())
if err != 0 {
return fmt.Errorf("err mclBn_FrEvaluatePolynomial")
}
@ -587,8 +1180,13 @@ func FrEvaluatePolynomial(y *Fr, c []Fr, x *Fr) error {
// G1EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ...
func G1EvaluatePolynomial(y *G1, c []G1, x *Fr) error {
n := len(c)
if n == 0 {
y.Clear()
return nil
}
// #nosec
err := C.mclBn_G1EvaluatePolynomial(y.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer())
err := C.mclBn_G1EvaluatePolynomial(y.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&c[0])), (C.size_t)(n), x.getPointer())
if err != 0 {
return fmt.Errorf("err mclBn_G1EvaluatePolynomial")
}
@ -597,8 +1195,13 @@ func G1EvaluatePolynomial(y *G1, c []G1, x *Fr) error {
// G2EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ...
func G2EvaluatePolynomial(y *G2, c []G2, x *Fr) error {
n := len(c)
if n == 0 {
y.Clear()
return nil
}
// #nosec
err := C.mclBn_G2EvaluatePolynomial(y.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer())
err := C.mclBn_G2EvaluatePolynomial(y.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&c[0])), (C.size_t)(n), x.getPointer())
if err != 0 {
return fmt.Errorf("err mclBn_G2EvaluatePolynomial")
}
@ -607,11 +1210,15 @@ func G2EvaluatePolynomial(y *G2, c []G2, x *Fr) error {
// FrLagrangeInterpolation --
func FrLagrangeInterpolation(out *Fr, xVec []Fr, yVec []Fr) error {
if len(xVec) != len(yVec) {
n := len(xVec)
if n == 0 {
return fmt.Errorf("err FrLagrangeInterpolation:n=0")
}
if n != len(yVec) {
return fmt.Errorf("err FrLagrangeInterpolation:bad size")
}
// #nosec
err := C.mclBn_FrLagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec)))
err := C.mclBn_FrLagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
if err != 0 {
return fmt.Errorf("err FrLagrangeInterpolation")
}
@ -620,11 +1227,15 @@ func FrLagrangeInterpolation(out *Fr, xVec []Fr, yVec []Fr) error {
// G1LagrangeInterpolation --
func G1LagrangeInterpolation(out *G1, xVec []Fr, yVec []G1) error {
if len(xVec) != len(yVec) {
n := len(xVec)
if n == 0 {
return fmt.Errorf("err G1LagrangeInterpolation:n=0")
}
if n != len(yVec) {
return fmt.Errorf("err G1LagrangeInterpolation:bad size")
}
// #nosec
err := C.mclBn_G1LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG1)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec)))
err := C.mclBn_G1LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG1)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
if err != 0 {
return fmt.Errorf("err G1LagrangeInterpolation")
}
@ -633,11 +1244,15 @@ func G1LagrangeInterpolation(out *G1, xVec []Fr, yVec []G1) error {
// G2LagrangeInterpolation --
func G2LagrangeInterpolation(out *G2, xVec []Fr, yVec []G2) error {
if len(xVec) != len(yVec) {
n := len(xVec)
if n == 0 {
return fmt.Errorf("err G2LagrangeInterpolation:n=0")
}
if n != len(yVec) {
return fmt.Errorf("err G2LagrangeInterpolation:bad size")
}
// #nosec
err := C.mclBn_G2LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec)))
err := C.mclBn_G2LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(n))
if err != 0 {
return fmt.Errorf("err G2LagrangeInterpolation")
}

@ -2,6 +2,7 @@ package mcl
import "testing"
import "fmt"
import "encoding/hex"
func testBadPointOfG2(t *testing.T) {
var Q G2
@ -71,6 +72,71 @@ func testNegAdd(t *testing.T) {
}
}
func testVecG1(t *testing.T) {
N := 50
xVec := make([]G1, N)
yVec := make([]Fr, N)
xVec[0].HashAndMapTo([]byte("aa"))
var R1, R2 G1
for i := 0; i < N; i++ {
if i > 0 {
G1Dbl(&xVec[i], &xVec[i-1])
}
yVec[i].SetByCSPRNG()
G1Mul(&R1, &xVec[i], &yVec[i])
G1Add(&R2, &R2, &R1)
}
G1MulVec(&R1, xVec, yVec)
if !R1.IsEqual(&R2) {
t.Errorf("wrong G1MulVec")
}
}
func testVecG2(t *testing.T) {
N := 50
xVec := make([]G2, N)
yVec := make([]Fr, N)
xVec[0].HashAndMapTo([]byte("aa"))
var R1, R2 G2
for i := 0; i < N; i++ {
if i > 0 {
G2Dbl(&xVec[i], &xVec[i-1])
}
yVec[i].SetByCSPRNG()
G2Mul(&R1, &xVec[i], &yVec[i])
G2Add(&R2, &R2, &R1)
}
G2MulVec(&R1, xVec, yVec)
if !R1.IsEqual(&R2) {
t.Errorf("wrong G2MulVec")
}
}
func testVecPairing(t *testing.T) {
N := 50
xVec := make([]G1, N)
yVec := make([]G2, N)
var e1, e2 GT
e1.SetInt64(1)
for i := 0; i < N; i++ {
xVec[0].HashAndMapTo([]byte("aa"))
yVec[0].HashAndMapTo([]byte("aa"))
Pairing(&e2, &xVec[i], &yVec[i])
GTMul(&e1, &e1, &e2)
}
MillerLoopVec(&e2, xVec, yVec)
FinalExp(&e2, &e2)
if !e1.IsEqual(&e2) {
t.Errorf("wrong MillerLoopVec")
}
}
func testVec(t *testing.T) {
testVecG1(t)
testVecG2(t)
testVecPairing(t)
}
func testPairing(t *testing.T) {
var a, b, ab Fr
err := a.SetString("123", 10)
@ -130,6 +196,44 @@ func testPairing(t *testing.T) {
}
}
func testSerialize(t *testing.T) {
var x, xx Fr
var y, yy Fp
var P, PP G1
var Q, QQ G2
var e, ee GT
x.SetByCSPRNG()
y.SetByCSPRNG()
P.HashAndMapTo([]byte("abc"))
G1Dbl(&P, &P)
Q.HashAndMapTo([]byte("abc"))
G2Dbl(&Q, &Q)
Pairing(&e, &P, &Q)
if xx.Deserialize(x.Serialize()) != nil || !x.IsEqual(&xx) {
t.Error("Serialize Fr")
}
if yy.Deserialize(y.Serialize()) != nil || !y.IsEqual(&yy) {
t.Error("Serialize Fp")
}
if PP.Deserialize(P.Serialize()) != nil || !P.IsEqual(&PP) {
t.Error("Serialize G1")
}
if QQ.Deserialize(Q.Serialize()) != nil || !Q.IsEqual(&QQ) {
t.Error("Serialize G2")
}
if ee.Deserialize(e.Serialize()) != nil || !e.IsEqual(&ee) {
t.Error("Serialize GT")
}
G1Dbl(&PP, &PP)
if PP.DeserializeUncompressed(P.SerializeUncompressed()) != nil || !P.IsEqual(&PP) {
t.Error("SerializeUncompressed G1")
}
G2Dbl(&QQ, &QQ)
if QQ.DeserializeUncompressed(Q.SerializeUncompressed()) != nil || !Q.IsEqual(&QQ) {
t.Error("SerializeUncompressed G2")
}
}
func testMcl(t *testing.T, c int) {
err := Init(c)
if err != nil {
@ -138,8 +242,47 @@ func testMcl(t *testing.T, c int) {
testHash(t)
testNegAdd(t)
testPairing(t)
testVec(t)
testGT(t)
testBadPointOfG2(t)
testSerialize(t)
}
func testETHserialize(t *testing.T) {
b := make([]byte, 32)
b[0] = 0x12
b[1] = 0x34
var x Fr
SetETHserialization(false)
x.Deserialize(b)
fmt.Printf("AAA x=%s\n", x.GetString(16))
SetETHserialization(true)
x.Deserialize(b)
fmt.Printf("AAA x=%s\n", x.GetString(16))
}
func testMapToG1(t *testing.T) {
SetMapToMode(IRTF)
fpHex := "0000000000000000000000000000000014406e5bfb9209256a3820879a29ac2f62d6aca82324bf3ae2aa7d3c54792043bd8c791fccdb080c1a52dc68b8b69350"
g1Hex := "ad7721bcdb7ce1047557776eb2659a444166dc6dd55c7ca6e240e21ae9aa18f529f04ac31d861b54faf3307692545db7"
fpBin, _ := hex.DecodeString(fpHex)
var x Fp
x.SetBigEndianMod(fpBin)
var P1 G1
err := MapToG1(&P1, &x)
if err != nil {
t.Fatal("MapToG1")
}
g1Str, _ := hex.DecodeString(g1Hex)
var P2 G1
err = P2.Deserialize(g1Str)
if err != nil {
t.Fatal("G1.Deserialize")
}
if !P1.IsEqual(&P2) {
t.Fatal("bad MapToG1")
}
}
func TestMclMain(t *testing.T) {
@ -153,5 +296,7 @@ func TestMclMain(t *testing.T) {
}
t.Log("BLS12_381")
testMcl(t, BLS12_381)
testETHserialize(t)
testMapToG1(t)
}
}

@ -1,104 +0,0 @@
import java.io.*;
import com.herumi.mcl.*;
/*
Bn256Test
*/
public class Bn256Test {
static {
String lib = "mcl_bn256";
String libName = System.mapLibraryName(lib);
System.out.println("libName : " + libName);
System.loadLibrary(lib);
}
public static void assertEquals(String msg, String x, String y) {
if (x.equals(y)) {
System.out.println("OK : " + msg);
} else {
System.out.println("NG : " + msg + ", x = " + x + ", y = " + y);
}
}
public static void assertBool(String msg, boolean b) {
if (b) {
System.out.println("OK : " + msg);
} else {
System.out.println("NG : " + msg);
}
}
public static void main(String argv[]) {
try {
Bn256.SystemInit();
Fr x = new Fr(5);
Fr y = new Fr(-2);
Fr z = new Fr(5);
assertBool("x != y", !x.equals(y));
assertBool("x == z", x.equals(z));
assertEquals("x == 5", x.toString(), "5");
Bn256.add(x, x, y);
assertEquals("x == 3", x.toString(), "3");
Bn256.mul(x, x, x);
assertEquals("x == 9", x.toString(), "9");
G1 P = new G1();
System.out.println("P=" + P);
P.set("-1", "1");
System.out.println("P=" + P);
Bn256.neg(P, P);
System.out.println("P=" + P);
String xa = "12723517038133731887338407189719511622662176727675373276651903807414909099441";
String xb = "4168783608814932154536427934509895782246573715297911553964171371032945126671";
String ya = "13891744915211034074451795021214165905772212241412891944830863846330766296736";
String yb = "7937318970632701341203597196594272556916396164729705624521405069090520231616";
G2 Q = new G2(xa, xb, ya, yb);
P.hashAndMapToG1("This is a pen");
{
String s = P.toString();
G1 P1 = new G1();
P1.setStr(s);
assertBool("P == P1", P1.equals(P));
}
GT e = new GT();
Bn256.pairing(e, P, Q);
GT e1 = new GT();
GT e2 = new GT();
Fr c = new Fr("1234567890123234928348230428394234");
G2 cQ = new G2(Q);
Bn256.mul(cQ, Q, c); // cQ = Q * c
Bn256.pairing(e1, P, cQ);
Bn256.pow(e2, e, c); // e2 = e^c
assertBool("e1 == e2", e1.equals(e2));
G1 cP = new G1(P);
Bn256.mul(cP, P, c); // cP = P * c
Bn256.pairing(e1, cP, Q);
assertBool("e1 == e2", e1.equals(e2));
BLSsignature(Q);
} catch (RuntimeException e) {
System.out.println("unknown exception :" + e);
}
}
public static void BLSsignature(G2 Q)
{
Fr s = new Fr();
s.setRand(); // secret key
System.out.println("secret key " + s);
G2 pub = new G2();
Bn256.mul(pub, Q, s); // public key = sQ
String m = "signature test";
G1 H = new G1();
H.hashAndMapToG1(m); // H = Hash(m)
G1 sign = new G1();
Bn256.mul(sign, H, s); // signature of m = s H
GT e1 = new GT();
GT e2 = new GT();
Bn256.pairing(e1, H, pub); // e1 = e(H, s Q)
Bn256.pairing(e2, sign, Q); // e2 = e(s H, Q);
assertBool("verify signature", e1.equals(e2));
}
}

@ -8,7 +8,7 @@ import com.herumi.mcl.*;
*/
public class ElgamalTest {
static {
String lib = "mcl_elgamal";
String lib = "mclelgamaljava";
String libName = System.mapLibraryName(lib);
System.out.println("libName : " + libName);
System.loadLibrary(lib);

@ -1,46 +1,50 @@
TOP_DIR=../..
include $(TOP_DIR)/common.mk
ifeq ($(UNAME_S),Darwin)
JAVA_INC=-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/
JAVA_INC_DIR?=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/JavaVM.framework/Headers/
JAVA_INC?=-I$(JAVA_INC_DIR)
CFLAGS+=$(JAVA_INC)/darwin
else
JAVA_INC=-I/usr/lib/jvm/default-java/include
JAVA_INC_DIR?=/usr/lib/jvm/default-java/include
JAVA_INC?=-I$(JAVA_INC_DIR)
#JAVA_INC=-I/usr/lib/jvm/java-7-openjdk-amd64/include
CFLAGS+=$(JAVA_INC)/linux
CFLAGS+=-z noexecstack
LDFLAGS+=-lrt
endif
CFLAGS+=$(JAVA_INC) $(JAVA_INC)/linux -I $(TOP_DIR)/include -I $(TOP_DIR)/../xbyak -I $(TOP_DIR)/../cybozulib/include -Wno-strict-aliasing
CFLAGS+=$(JAVA_INC) -I $(TOP_DIR)/include -I -Wno-strict-aliasing
MCL_LIB=$(TOP_DIR)/lib/libmcl.a
PACKAGE_NAME=com.herumi.mcl
PACKAGE_DIR=$(subst .,/,$(PACKAGE_NAME))
ELGAMAL_LIB=$(TOP_DIR)/bin/libmcl_elgamal.$(LIB_SUF)
BN256_LIB=$(TOP_DIR)/bin/libmcl_bn256.$(LIB_SUF)
JAVA_EXE=cd $(TOP_DIR)/bin && LD_LIBRARY_PATH=./:$(LD_LIBRARY_PATH) java -classpath ../ffi/java
ELGAMAL_LIB=$(TOP_DIR)/lib/libmclelgamaljava.$(LIB_SUF)
MCLJAVA_LIB=$(TOP_DIR)/lib/libmcljava.$(LIB_SUF)
JAVA_EXE=cd $(TOP_DIR)/lib && LD_LIBRARY_PATH=../lib:$(LD_LIBRARY_PATH) java -classpath ../ffi/java
all: $(ELGAMAL_LIB)
elgamal_wrap.cxx: elgamal.i elgamal_impl.hpp
$(MKDIR) $(PACKAGE_DIR)
swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall elgamal.i
bn256_wrap.cxx: bn256.i bn256_impl.hpp
mcl_wrap.cxx: mcl.i mcl_impl.hpp
$(MKDIR) $(PACKAGE_DIR)
swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall bn256.i
swig -java -package $(PACKAGE_NAME) -outdir $(PACKAGE_DIR) -c++ -Wall mcl.i
$(MCL_LIB):
make -C $(TOP_DIR)
make -C $(TOP_DIR) lib/libmcl.a
$(ELGAMAL_LIB): elgamal_wrap.cxx $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(CFLAGS) $(LDFLAGS) $(MCL_LIB) -shared
$(PRE)$(CXX) $< -o $@ $(CFLAGS) $(MCL_LIB) $(LDFLAGS) -shared
$(BN256_LIB): bn256_wrap.cxx $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(CFLAGS) $(LDFLAGS) $(MCL_LIB) -shared
$(MCLJAVA_LIB): mcl_wrap.cxx $(MCL_LIB)
$(PRE)$(CXX) $< -o $@ $(CFLAGS) $(MCL_LIB) $(LDFLAGS) -shared
%.class: %.java
javac $<
ElgamalTest.class: ElgamalTest.java $(ELGAMAL_LIB)
Bn256Test.class: Bn256Test.java $(BN256_LIB)
MclTest.class: MclTest.java $(MCLJAVA_LIB)
jar:
jar cvf mcl.jar com
@ -49,16 +53,17 @@ test_elgamal: ElgamalTest.class $(ELGAMAL_LIB)
$(JAVA_EXE) ElgamalTest
$(JAVA_EXE) ElgamalTest -e NIST_P192
$(JAVA_EXE) ElgamalTest -e NIST_P256 -h sha256
$(JAVA_EXE) ElgamalTest -e secp256k1 -h sha256
$(JAVA_EXE) ElgamalTest -e NIST_P384 -h sha384
$(JAVA_EXE) ElgamalTest -e NIST_P521 -h sha512
# $(JAVA_EXE) ElgamalTest -e NIST_P521 -h sha512
test_bn256: Bn256Test.class $(BN256_LIB)
$(JAVA_EXE) Bn256Test
test_mcl: MclTest.class $(MCLJAVA_LIB)
$(JAVA_EXE) MclTest
test:
$(MAKE) test_elgamal
$(MAKE) test_bn256
$(MAKE) test_mcl
clean:
rm -rf *.class $(ELGAMAL_LIB) $(PACKAGE_DIR)/*.class *_wrap.cxx
rm -rf *.class $(ELGAMAL_LIB) $(MCLJAVA_LIB) $(PACKAGE_DIR)/*.class *_wrap.cxx

@ -0,0 +1,160 @@
import java.io.*;
import com.herumi.mcl.*;
/*
MclTest
*/
public class MclTest {
static {
String lib = "mcljava";
String libName = System.mapLibraryName(lib);
System.out.println("libName : " + libName);
System.loadLibrary(lib);
}
public static int errN = 0;
public static void assertEquals(String msg, String x, String y) {
if (x.equals(y)) {
System.out.println("OK : " + msg);
} else {
System.out.println("NG : " + msg + ", x = " + x + ", y = " + y);
errN++;
}
}
public static void assertBool(String msg, boolean b) {
if (b) {
System.out.println("OK : " + msg);
} else {
System.out.println("NG : " + msg);
errN++;
}
}
public static void testCurve(int curveType, String name) {
try {
System.out.println("curve=" + name);
Mcl.SystemInit(curveType);
Fr x = new Fr(5);
Fr y = new Fr(-2);
Fr z = new Fr(5);
assertBool("x != y", !x.equals(y));
assertBool("x == z", x.equals(z));
assertEquals("x == 5", x.toString(), "5");
Mcl.add(x, x, y);
assertEquals("x == 3", x.toString(), "3");
Mcl.mul(x, x, x);
assertEquals("x == 9", x.toString(), "9");
assertEquals("x == 12", (new Fr("12")).toString(), "12");
assertEquals("x == 18", (new Fr("12", 16)).toString(), "18");
assertEquals("x == ff", (new Fr("255")).toString(16), "ff");
Mcl.inv(y, x);
Mcl.mul(x, y, x);
assertBool("x == 1", x.isOne());
{
byte[] b = x.serialize();
Fr t = new Fr();
t.deserialize(b);
assertBool("serialize", x.equals(t));
t.setLittleEndianMod(b);
assertBool("setLittleEndianMod", x.equals(t));
t.setHashOf(b);
assertBool("setHashOf", !x.equals(t));
Fr u = new Fr();
u.setHashOf(new byte[]{1,2,3});
assertBool("setHashOf - different", !u.equals(t));
}
G1 P = new G1();
System.out.println("P=" + P);
Mcl.hashAndMapToG1(P, "test".getBytes());
System.out.println("P=" + P);
byte[] buf = { 1, 2, 3, 4 };
Mcl.hashAndMapToG1(P, buf);
System.out.println("P=" + P);
Mcl.neg(P, P);
System.out.println("P=" + P);
{
byte[] b = P.serialize();
G1 t = new G1();
t.deserialize(b);
assertBool("serialize", P.equals(t));
}
G2 Q = new G2();
Mcl.hashAndMapToG2(Q, "abc".getBytes());
System.out.println("Q=" + Q);
Mcl.hashAndMapToG1(P, "This is a pen".getBytes());
{
String s = P.toString();
G1 P1 = new G1();
P1.setStr(s);
assertBool("P == P1", P1.equals(P));
}
{
byte[] b = Q.serialize();
G2 t = new G2();
t.deserialize(b);
assertBool("serialize", Q.equals(t));
}
GT e = new GT();
Mcl.pairing(e, P, Q);
GT e1 = new GT();
GT e2 = new GT();
Fr c = new Fr("1234567890123234928348230428394234");
System.out.println("c=" + c);
G2 cQ = new G2(Q);
Mcl.mul(cQ, Q, c); // cQ = Q * c
Mcl.pairing(e1, P, cQ);
Mcl.pow(e2, e, c); // e2 = e^c
assertBool("e1 == e2", e1.equals(e2));
{
byte[] b = e1.serialize();
GT t = new GT();
t.deserialize(b);
assertBool("serialize", e1.equals(t));
}
G1 cP = new G1(P);
Mcl.mul(cP, P, c); // cP = P * c
Mcl.pairing(e1, cP, Q);
assertBool("e1 == e2", e1.equals(e2));
Mcl.inv(e1, e1);
Mcl.mul(e1, e1, e2);
e2.setStr("1 0 0 0 0 0 0 0 0 0 0 0");
assertBool("e1 == 1", e1.equals(e2));
assertBool("e1 == 1", e1.isOne());
BLSsignature(Q);
if (errN == 0) {
System.out.println("all test passed");
} else {
System.out.println("ERR=" + errN);
}
} catch (RuntimeException e) {
System.out.println("unknown exception :" + e);
}
}
public static void BLSsignature(G2 Q)
{
Fr s = new Fr();
s.setByCSPRNG(); // secret key
System.out.println("secret key " + s);
G2 pub = new G2();
Mcl.mul(pub, Q, s); // public key = sQ
byte[] m = "signature test".getBytes();
G1 H = new G1();
Mcl.hashAndMapToG1(H, m); // H = Hash(m)
G1 sign = new G1();
Mcl.mul(sign, H, s); // signature of m = s H
GT e1 = new GT();
GT e2 = new GT();
Mcl.pairing(e1, H, pub); // e1 = e(H, s Q)
Mcl.pairing(e2, sign, Q); // e2 = e(s H, Q);
assertBool("verify signature", e1.equals(e2));
}
public static void main(String argv[]) {
testCurve(Mcl.BN254, "BN254");
testCurve(Mcl.BLS12_381, "BLS12_381");
}
}

@ -0,0 +1,39 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cpp .ll .cxx
LOCAL_MODULE := mcljava
LOCAL_MCL_DIR := $(LOCAL_PATH)/../../../../
ifeq ($(TARGET_ARCH_ABI),x86_64)
MY_BIT := 64
endif
ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
MY_BIT := 64
endif
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
MY_BIT := 32
endif
ifeq ($(TARGET_ARCH_ABI),x86)
MY_BIT := 32
endif
ifeq ($(MY_BIT),64)
MY_BASE_LL := $(LOCAL_MCL_DIR)/src/base64.ll
LOCAL_CPPFLAGS += -DMCL_SIZEOF_UNIT=8
endif
ifeq ($(MY_BIT),32)
MY_BASE_LL := $(LOCAL_MCL_DIR)/src/base32.ll
LOCAL_CPPFLAGS += -DMCL_SIZEOF_UNIT=4
endif
LOCAL_SRC_FILES := $(LOCAL_MCL_DIR)/ffi/java/mcl_wrap.cxx $(LOCAL_MCL_DIR)/src/bn_c384_256.cpp $(LOCAL_MCL_DIR)/src/fp.cpp $(MY_BASE_LL)
LOCAL_C_INCLUDES := $(LOCAL_MCL_DIR)/include $(LOCAL_MCL_DIR)/src $(LOCAL_MCL_DIR)/ffi/java
LOCAL_CPPFLAGS += -DMCL_DONT_USE_XBYAK
LOCAL_CPPFLAGS += -O3 -DNDEBUG -fPIC -DMCL_DONT_USE_OPENSSL -DMCL_LLVM_BMI2=0 -DMCL_USE_LLVM=1 -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER -DMCL_MAX_BIT_SIZE=384
LOCAL_CPPFLAGS += -fno-threadsafe-statics
#LOCAL_CPPFLAGS+=-fno-exceptions -fno-rtti -DCYBOZU_DONT_USE_EXCEPTION -DCYBOZU_DONT_USE_STRING -std=c++03
#LOCAL_CPPFLAGS += -DBLS_ETH
#LOCAL_LDLIBS := -llog #-Wl,--no-warn-shared-textrel
#include $(BUILD_STATIC_LIBRARY)
include $(BUILD_SHARED_LIBRARY)

@ -0,0 +1,4 @@
APP_ABI := arm64-v8a armeabi-v7a x86_64
APP_PLATFORM := android-19
APP_STL := c++_static
APP_CPPFLAGS := -fexceptions

@ -1,31 +0,0 @@
%module Bn256
%include "std_string.i"
%include "std_except.i"
%{
#include <cybozu/random_generator.hpp>
#include <cybozu/crypto.hpp>
#include <mcl/bn256.hpp>
struct Param {
cybozu::RandomGenerator rg;
static inline Param& getParam()
{
static Param p;
return p;
}
};
static void HashAndMapToG1(mcl::bn256::G1& P, const std::string& m)
{
std::string digest = cybozu::crypto::Hash::digest(cybozu::crypto::Hash::N_SHA256, m);
mcl::bn256::Fp t;
t.setArrayMask(digest.c_str(), digest.size());
mcl::bn256::BN::param.mapTo.calcG1(P, t);
}
#include "bn256_impl.hpp"
%}
%include "bn256_impl.hpp"

@ -1,249 +0,0 @@
#include <mcl/bn256.hpp>
#include <stdint.h>
#include <sstream>
void SystemInit() throw(std::exception)
{
mcl::bn256::initPairing();
}
class G1;
class G2;
class GT;
/*
Fr = Z / rZ
*/
class Fr {
mcl::bn256::Fr self_;
friend class G1;
friend class G2;
friend class GT;
friend void neg(Fr& y, const Fr& x);
friend void add(Fr& z, const Fr& x, const Fr& y);
friend void sub(Fr& z, const Fr& x, const Fr& y);
friend void mul(Fr& z, const Fr& x, const Fr& y);
friend void mul(G1& z, const G1& x, const Fr& y);
friend void mul(G2& z, const G2& x, const Fr& y);
friend void div(Fr& z, const Fr& x, const Fr& y);
friend void pow(GT& z, const GT& x, const Fr& y);
public:
Fr() {}
Fr(const Fr& rhs) : self_(rhs.self_) {}
Fr(int x) : self_(x) {}
Fr(const std::string& str) throw(std::exception)
: self_(str) {}
bool equals(const Fr& rhs) const { return self_ == rhs.self_; }
void setStr(const std::string& str) throw(std::exception)
{
self_.setStr(str);
}
void setInt(int x)
{
self_ = x;
}
void clear()
{
self_.clear();
}
void setRand()
{
self_.setRand(Param::getParam().rg);
}
std::string toString() const throw(std::exception)
{
return self_.getStr();
}
};
void neg(Fr& y, const Fr& x)
{
mcl::bn256::Fr::neg(y.self_, x.self_);
}
void add(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn256::Fr::add(z.self_, x.self_, y.self_);
}
void sub(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn256::Fr::sub(z.self_, x.self_, y.self_);
}
void mul(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn256::Fr::mul(z.self_, x.self_, y.self_);
}
void div(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn256::Fr::div(z.self_, x.self_, y.self_);
}
/*
#G1 = r
*/
class G1 {
mcl::bn256::G1 self_;
friend void neg(G1& y, const G1& x);
friend void dbl(G1& y, const G1& x);
friend void add(G1& z, const G1& x, const G1& y);
friend void sub(G1& z, const G1& x, const G1& y);
friend void mul(G1& z, const G1& x, const Fr& y);
friend void pairing(GT& e, const G1& P, const G2& Q);
public:
G1() {}
G1(const G1& rhs) : self_(rhs.self_) {}
G1(const std::string& x, const std::string& y) throw(std::exception)
: self_(mcl::bn256::Fp(x), mcl::bn256::Fp(y))
{
}
bool equals(const G1& rhs) const { return self_ == rhs.self_; }
void set(const std::string& x, const std::string& y)
{
self_.set(mcl::bn256::Fp(x), mcl::bn256::Fp(y));
}
void hashAndMapToG1(const std::string& m) throw(std::exception)
{
HashAndMapToG1(self_, m);
}
void clear()
{
self_.clear();
}
/*
compressed format
*/
void setStr(const std::string& str) throw(std::exception)
{
self_.setStr(str);
}
std::string toString() const throw(std::exception)
{
return self_.getStr();
}
};
void neg(G1& y, const G1& x)
{
mcl::bn256::G1::neg(y.self_, x.self_);
}
void dbl(G1& y, const G1& x)
{
mcl::bn256::G1::dbl(y.self_, x.self_);
}
void add(G1& z, const G1& x, const G1& y)
{
mcl::bn256::G1::add(z.self_, x.self_, y.self_);
}
void sub(G1& z, const G1& x, const G1& y)
{
mcl::bn256::G1::sub(z.self_, x.self_, y.self_);
}
void mul(G1& z, const G1& x, const Fr& y)
{
mcl::bn256::G1::mul(z.self_, x.self_, y.self_);
}
/*
#G2 = r
*/
class G2 {
mcl::bn256::G2 self_;
friend void neg(G2& y, const G2& x);
friend void dbl(G2& y, const G2& x);
friend void add(G2& z, const G2& x, const G2& y);
friend void sub(G2& z, const G2& x, const G2& y);
friend void mul(G2& z, const G2& x, const Fr& y);
friend void pairing(GT& e, const G1& P, const G2& Q);
public:
G2() {}
G2(const G2& rhs) : self_(rhs.self_) {}
G2(const std::string& xa, const std::string& xb, const std::string& ya, const std::string& yb) throw(std::exception)
: self_(mcl::bn256::Fp2(xa, xb), mcl::bn256::Fp2(ya, yb))
{
}
bool equals(const G2& rhs) const { return self_ == rhs.self_; }
void set(const std::string& xa, const std::string& xb, const std::string& ya, const std::string& yb)
{
self_.set(mcl::bn256::Fp2(xa, xb), mcl::bn256::Fp2(ya, yb));
}
void clear()
{
self_.clear();
}
/*
compressed format
*/
void setStr(const std::string& str) throw(std::exception)
{
self_.setStr(str);
}
std::string toString() const throw(std::exception)
{
return self_.getStr();
}
};
void neg(G2& y, const G2& x)
{
mcl::bn256::G2::neg(y.self_, x.self_);
}
void dbl(G2& y, const G2& x)
{
mcl::bn256::G2::dbl(y.self_, x.self_);
}
void add(G2& z, const G2& x, const G2& y)
{
mcl::bn256::G2::add(z.self_, x.self_, y.self_);
}
void sub(G2& z, const G2& x, const G2& y)
{
mcl::bn256::G2::sub(z.self_, x.self_, y.self_);
}
void mul(G2& z, const G2& x, const Fr& y)
{
mcl::bn256::G2::mul(z.self_, x.self_, y.self_);
}
/*
#GT = r
*/
class GT {
mcl::bn256::Fp12 self_;
friend void mul(GT& z, const GT& x, const GT& y);
friend void pow(GT& z, const GT& x, const Fr& y);
friend void pairing(GT& e, const G1& P, const G2& Q);
public:
GT() {}
GT(const GT& rhs) : self_(rhs.self_) {}
bool equals(const GT& rhs) const { return self_ == rhs.self_; }
void clear()
{
self_.clear();
}
void setStr(const std::string& str) throw(std::exception)
{
std::istringstream iss(str);
iss >> self_;
}
std::string toString() const throw(std::exception)
{
std::ostringstream oss;
oss << self_;
return oss.str();
}
};
void mul(GT& z, const GT& x, const GT& y)
{
mcl::bn256::Fp12::mul(z.self_, x.self_, y.self_);
}
void pow(GT& z, const GT& x, const Fr& y)
{
mcl::bn256::Fp12::pow(z.self_, x.self_, y.self_);
}
void pairing(GT& e, const G1& P, const G2& Q)
{
mcl::bn256::pairing(e.self_, P.self_, Q.self_);
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,67 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class CipherText {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected CipherText(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(CipherText obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
ElgamalJNI.delete_CipherText(swigCPtr);
}
swigCPtr = 0;
}
}
public String toStr() {
return ElgamalJNI.CipherText_toStr(swigCPtr, this);
}
public String toString() {
return ElgamalJNI.CipherText_toString(swigCPtr, this);
}
public void fromStr(String str) {
ElgamalJNI.CipherText_fromStr(swigCPtr, this, str);
}
public void add(CipherText c) {
ElgamalJNI.CipherText_add(swigCPtr, this, CipherText.getCPtr(c), c);
}
public void mul(int m) {
ElgamalJNI.CipherText_mul__SWIG_0(swigCPtr, this, m);
}
public void mul(String str) {
ElgamalJNI.CipherText_mul__SWIG_1(swigCPtr, this, str);
}
public CipherText() {
this(ElgamalJNI.new_CipherText(), true);
}
}

@ -0,0 +1,38 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class Elgamal {
public static SWIGTYPE_p_bool new_p_bool() {
long cPtr = ElgamalJNI.new_p_bool();
return (cPtr == 0) ? null : new SWIGTYPE_p_bool(cPtr, false);
}
public static SWIGTYPE_p_bool copy_p_bool(boolean value) {
long cPtr = ElgamalJNI.copy_p_bool(value);
return (cPtr == 0) ? null : new SWIGTYPE_p_bool(cPtr, false);
}
public static void delete_p_bool(SWIGTYPE_p_bool obj) {
ElgamalJNI.delete_p_bool(SWIGTYPE_p_bool.getCPtr(obj));
}
public static void p_bool_assign(SWIGTYPE_p_bool obj, boolean value) {
ElgamalJNI.p_bool_assign(SWIGTYPE_p_bool.getCPtr(obj), value);
}
public static boolean p_bool_value(SWIGTYPE_p_bool obj) {
return ElgamalJNI.p_bool_value(SWIGTYPE_p_bool.getCPtr(obj));
}
public static void SystemInit(String param) {
ElgamalJNI.SystemInit(param);
}
}

@ -0,0 +1,51 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class ElgamalJNI {
public final static native long new_p_bool();
public final static native long copy_p_bool(boolean jarg1);
public final static native void delete_p_bool(long jarg1);
public final static native void p_bool_assign(long jarg1, boolean jarg2);
public final static native boolean p_bool_value(long jarg1);
public final static native void SystemInit(String jarg1);
public final static native String CipherText_toStr(long jarg1, CipherText jarg1_);
public final static native String CipherText_toString(long jarg1, CipherText jarg1_);
public final static native void CipherText_fromStr(long jarg1, CipherText jarg1_, String jarg2);
public final static native void CipherText_add(long jarg1, CipherText jarg1_, long jarg2, CipherText jarg2_);
public final static native void CipherText_mul__SWIG_0(long jarg1, CipherText jarg1_, int jarg2);
public final static native void CipherText_mul__SWIG_1(long jarg1, CipherText jarg1_, String jarg2);
public final static native long new_CipherText();
public final static native void delete_CipherText(long jarg1);
public final static native String PublicKey_toStr(long jarg1, PublicKey jarg1_);
public final static native String PublicKey_toString(long jarg1, PublicKey jarg1_);
public final static native void PublicKey_fromStr(long jarg1, PublicKey jarg1_, String jarg2);
public final static native void PublicKey_save(long jarg1, PublicKey jarg1_, String jarg2);
public final static native void PublicKey_load(long jarg1, PublicKey jarg1_, String jarg2);
public final static native void PublicKey_enc__SWIG_0(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, int jarg3);
public final static native void PublicKey_enc__SWIG_1(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, String jarg3);
public final static native void PublicKey_rerandomize(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_);
public final static native void PublicKey_add__SWIG_0(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, int jarg3);
public final static native void PublicKey_add__SWIG_1(long jarg1, PublicKey jarg1_, long jarg2, CipherText jarg2_, String jarg3);
public final static native long new_PublicKey();
public final static native void delete_PublicKey(long jarg1);
public final static native String PrivateKey_toStr(long jarg1, PrivateKey jarg1_);
public final static native String PrivateKey_toString(long jarg1, PrivateKey jarg1_);
public final static native void PrivateKey_fromStr(long jarg1, PrivateKey jarg1_, String jarg2);
public final static native void PrivateKey_save(long jarg1, PrivateKey jarg1_, String jarg2);
public final static native void PrivateKey_load(long jarg1, PrivateKey jarg1_, String jarg2);
public final static native void PrivateKey_init(long jarg1, PrivateKey jarg1_);
public final static native long PrivateKey_getPublicKey(long jarg1, PrivateKey jarg1_);
public final static native int PrivateKey_dec__SWIG_0(long jarg1, PrivateKey jarg1_, long jarg2, CipherText jarg2_, long jarg3);
public final static native int PrivateKey_dec__SWIG_1(long jarg1, PrivateKey jarg1_, long jarg2, CipherText jarg2_);
public final static native void PrivateKey_setCache(long jarg1, PrivateKey jarg1_, int jarg2, int jarg3);
public final static native void PrivateKey_clearCache(long jarg1, PrivateKey jarg1_);
public final static native long new_PrivateKey();
public final static native void delete_PrivateKey(long jarg1);
}

@ -0,0 +1,105 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class Fp {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected Fp(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(Fp obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_Fp(swigCPtr);
}
swigCPtr = 0;
}
}
public Fp() {
this(MclJNI.new_Fp__SWIG_0(), true);
}
public Fp(Fp rhs) {
this(MclJNI.new_Fp__SWIG_1(Fp.getCPtr(rhs), rhs), true);
}
public Fp(int x) {
this(MclJNI.new_Fp__SWIG_2(x), true);
}
public Fp(String str, int base) {
this(MclJNI.new_Fp__SWIG_3(str, base), true);
}
public Fp(String str) {
this(MclJNI.new_Fp__SWIG_4(str), true);
}
public boolean equals(Fp rhs) {
return MclJNI.Fp_equals(swigCPtr, this, Fp.getCPtr(rhs), rhs);
}
public boolean isZero() {
return MclJNI.Fp_isZero(swigCPtr, this);
}
public boolean isOne() {
return MclJNI.Fp_isOne(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.Fp_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.Fp_setStr__SWIG_1(swigCPtr, this, str);
}
public void setInt(int x) {
MclJNI.Fp_setInt(swigCPtr, this, x);
}
public void clear() {
MclJNI.Fp_clear(swigCPtr, this);
}
public void setByCSPRNG() {
MclJNI.Fp_setByCSPRNG(swigCPtr, this);
}
public String toString(int base) {
return MclJNI.Fp_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.Fp_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.Fp_deserialize(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.Fp_serialize(swigCPtr, this); }
}

@ -0,0 +1,113 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class Fr {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected Fr(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(Fr obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_Fr(swigCPtr);
}
swigCPtr = 0;
}
}
public Fr() {
this(MclJNI.new_Fr__SWIG_0(), true);
}
public Fr(Fr rhs) {
this(MclJNI.new_Fr__SWIG_1(Fr.getCPtr(rhs), rhs), true);
}
public Fr(int x) {
this(MclJNI.new_Fr__SWIG_2(x), true);
}
public Fr(String str, int base) {
this(MclJNI.new_Fr__SWIG_3(str, base), true);
}
public Fr(String str) {
this(MclJNI.new_Fr__SWIG_4(str), true);
}
public boolean equals(Fr rhs) {
return MclJNI.Fr_equals(swigCPtr, this, Fr.getCPtr(rhs), rhs);
}
public boolean isZero() {
return MclJNI.Fr_isZero(swigCPtr, this);
}
public boolean isOne() {
return MclJNI.Fr_isOne(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.Fr_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.Fr_setStr__SWIG_1(swigCPtr, this, str);
}
public void setInt(int x) {
MclJNI.Fr_setInt(swigCPtr, this, x);
}
public void clear() {
MclJNI.Fr_clear(swigCPtr, this);
}
public void setByCSPRNG() {
MclJNI.Fr_setByCSPRNG(swigCPtr, this);
}
public String toString(int base) {
return MclJNI.Fr_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.Fr_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.Fr_deserialize(swigCPtr, this, cbuf);
}
public void setLittleEndianMod(byte[] cbuf) {
MclJNI.Fr_setLittleEndianMod(swigCPtr, this, cbuf);
}
public void setHashOf(byte[] cbuf) {
MclJNI.Fr_setHashOf(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.Fr_serialize(swigCPtr, this); }
}

@ -0,0 +1,93 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class G1 {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected G1(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(G1 obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_G1(swigCPtr);
}
swigCPtr = 0;
}
}
public G1() {
this(MclJNI.new_G1__SWIG_0(), true);
}
public G1(G1 rhs) {
this(MclJNI.new_G1__SWIG_1(G1.getCPtr(rhs), rhs), true);
}
public G1(Fp x, Fp y) {
this(MclJNI.new_G1__SWIG_2(Fp.getCPtr(x), x, Fp.getCPtr(y), y), true);
}
public boolean equals(G1 rhs) {
return MclJNI.G1_equals(swigCPtr, this, G1.getCPtr(rhs), rhs);
}
public boolean isZero() {
return MclJNI.G1_isZero(swigCPtr, this);
}
public boolean isValidOrder() {
return MclJNI.G1_isValidOrder(swigCPtr, this);
}
public void set(Fp x, Fp y) {
MclJNI.G1_set(swigCPtr, this, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public void clear() {
MclJNI.G1_clear(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.G1_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.G1_setStr__SWIG_1(swigCPtr, this, str);
}
public String toString(int base) {
return MclJNI.G1_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.G1_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.G1_deserialize(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.G1_serialize(swigCPtr, this); }
}

@ -0,0 +1,89 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class G2 {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected G2(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(G2 obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_G2(swigCPtr);
}
swigCPtr = 0;
}
}
public G2() {
this(MclJNI.new_G2__SWIG_0(), true);
}
public G2(G2 rhs) {
this(MclJNI.new_G2__SWIG_1(G2.getCPtr(rhs), rhs), true);
}
public G2(Fp ax, Fp ay, Fp bx, Fp by) {
this(MclJNI.new_G2__SWIG_2(Fp.getCPtr(ax), ax, Fp.getCPtr(ay), ay, Fp.getCPtr(bx), bx, Fp.getCPtr(by), by), true);
}
public boolean equals(G2 rhs) {
return MclJNI.G2_equals(swigCPtr, this, G2.getCPtr(rhs), rhs);
}
public boolean isZero() {
return MclJNI.G2_isZero(swigCPtr, this);
}
public void set(Fp ax, Fp ay, Fp bx, Fp by) {
MclJNI.G2_set(swigCPtr, this, Fp.getCPtr(ax), ax, Fp.getCPtr(ay), ay, Fp.getCPtr(bx), bx, Fp.getCPtr(by), by);
}
public void clear() {
MclJNI.G2_clear(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.G2_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.G2_setStr__SWIG_1(swigCPtr, this, str);
}
public String toString(int base) {
return MclJNI.G2_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.G2_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.G2_deserialize(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.G2_serialize(swigCPtr, this); }
}

@ -0,0 +1,81 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class GT {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected GT(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(GT obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
MclJNI.delete_GT(swigCPtr);
}
swigCPtr = 0;
}
}
public GT() {
this(MclJNI.new_GT__SWIG_0(), true);
}
public GT(GT rhs) {
this(MclJNI.new_GT__SWIG_1(GT.getCPtr(rhs), rhs), true);
}
public boolean equals(GT rhs) {
return MclJNI.GT_equals(swigCPtr, this, GT.getCPtr(rhs), rhs);
}
public boolean isOne() {
return MclJNI.GT_isOne(swigCPtr, this);
}
public void clear() {
MclJNI.GT_clear(swigCPtr, this);
}
public void setStr(String str, int base) {
MclJNI.GT_setStr__SWIG_0(swigCPtr, this, str, base);
}
public void setStr(String str) {
MclJNI.GT_setStr__SWIG_1(swigCPtr, this, str);
}
public String toString(int base) {
return MclJNI.GT_toString__SWIG_0(swigCPtr, this, base);
}
public String toString() {
return MclJNI.GT_toString__SWIG_1(swigCPtr, this);
}
public void deserialize(byte[] cbuf) {
MclJNI.GT_deserialize(swigCPtr, this, cbuf);
}
public byte[] serialize() { return MclJNI.GT_serialize(swigCPtr, this); }
}

@ -0,0 +1,128 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class Mcl implements MclConstants {
public static void SystemInit(int curveType) {
MclJNI.SystemInit(curveType);
}
public static void neg(Fr y, Fr x) {
MclJNI.neg__SWIG_0(Fr.getCPtr(y), y, Fr.getCPtr(x), x);
}
public static void inv(Fr y, Fr x) {
MclJNI.inv__SWIG_0(Fr.getCPtr(y), y, Fr.getCPtr(x), x);
}
public static void add(Fr z, Fr x, Fr y) {
MclJNI.add__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void sub(Fr z, Fr x, Fr y) {
MclJNI.sub__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void mul(Fr z, Fr x, Fr y) {
MclJNI.mul__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void mul(G1 z, G1 x, Fr y) {
MclJNI.mul__SWIG_1(G1.getCPtr(z), z, G1.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void mul(G2 z, G2 x, Fr y) {
MclJNI.mul__SWIG_2(G2.getCPtr(z), z, G2.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void div(Fr z, Fr x, Fr y) {
MclJNI.div__SWIG_0(Fr.getCPtr(z), z, Fr.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void pow(GT z, GT x, Fr y) {
MclJNI.pow(GT.getCPtr(z), z, GT.getCPtr(x), x, Fr.getCPtr(y), y);
}
public static void neg(Fp y, Fp x) {
MclJNI.neg__SWIG_1(Fp.getCPtr(y), y, Fp.getCPtr(x), x);
}
public static void inv(Fp y, Fp x) {
MclJNI.inv__SWIG_1(Fp.getCPtr(y), y, Fp.getCPtr(x), x);
}
public static void add(Fp z, Fp x, Fp y) {
MclJNI.add__SWIG_1(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public static void sub(Fp z, Fp x, Fp y) {
MclJNI.sub__SWIG_1(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public static void mul(Fp z, Fp x, Fp y) {
MclJNI.mul__SWIG_3(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public static void div(Fp z, Fp x, Fp y) {
MclJNI.div__SWIG_1(Fp.getCPtr(z), z, Fp.getCPtr(x), x, Fp.getCPtr(y), y);
}
public static void neg(G1 y, G1 x) {
MclJNI.neg__SWIG_2(G1.getCPtr(y), y, G1.getCPtr(x), x);
}
public static void dbl(G1 y, G1 x) {
MclJNI.dbl__SWIG_0(G1.getCPtr(y), y, G1.getCPtr(x), x);
}
public static void add(G1 z, G1 x, G1 y) {
MclJNI.add__SWIG_2(G1.getCPtr(z), z, G1.getCPtr(x), x, G1.getCPtr(y), y);
}
public static void sub(G1 z, G1 x, G1 y) {
MclJNI.sub__SWIG_2(G1.getCPtr(z), z, G1.getCPtr(x), x, G1.getCPtr(y), y);
}
public static void pairing(GT e, G1 P, G2 Q) {
MclJNI.pairing(GT.getCPtr(e), e, G1.getCPtr(P), P, G2.getCPtr(Q), Q);
}
public static void hashAndMapToG1(G1 P, byte[] cbuf) {
MclJNI.hashAndMapToG1(G1.getCPtr(P), P, cbuf);
}
public static void neg(G2 y, G2 x) {
MclJNI.neg__SWIG_3(G2.getCPtr(y), y, G2.getCPtr(x), x);
}
public static void dbl(G2 y, G2 x) {
MclJNI.dbl__SWIG_1(G2.getCPtr(y), y, G2.getCPtr(x), x);
}
public static void add(G2 z, G2 x, G2 y) {
MclJNI.add__SWIG_3(G2.getCPtr(z), z, G2.getCPtr(x), x, G2.getCPtr(y), y);
}
public static void sub(G2 z, G2 x, G2 y) {
MclJNI.sub__SWIG_3(G2.getCPtr(z), z, G2.getCPtr(x), x, G2.getCPtr(y), y);
}
public static void hashAndMapToG2(G2 P, byte[] cbuf) {
MclJNI.hashAndMapToG2(G2.getCPtr(P), P, cbuf);
}
public static void mul(GT z, GT x, GT y) {
MclJNI.mul__SWIG_4(GT.getCPtr(z), z, GT.getCPtr(x), x, GT.getCPtr(y), y);
}
public static void inv(GT y, GT x) {
MclJNI.inv__SWIG_2(GT.getCPtr(y), y, GT.getCPtr(x), x);
}
}

@ -0,0 +1,14 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public interface MclConstants {
public final static int BN254 = 0;
public final static int BLS12_381 = 5;
}

@ -0,0 +1,120 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class MclJNI {
public final static native void SystemInit(int jarg1);
public final static native void neg__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_);
public final static native void inv__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_);
public final static native void add__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_);
public final static native void sub__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_);
public final static native void mul__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_);
public final static native void mul__SWIG_1(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_, long jarg3, Fr jarg3_);
public final static native void mul__SWIG_2(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_, long jarg3, Fr jarg3_);
public final static native void div__SWIG_0(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_, long jarg3, Fr jarg3_);
public final static native void pow(long jarg1, GT jarg1_, long jarg2, GT jarg2_, long jarg3, Fr jarg3_);
public final static native long new_Fr__SWIG_0();
public final static native long new_Fr__SWIG_1(long jarg1, Fr jarg1_);
public final static native long new_Fr__SWIG_2(int jarg1);
public final static native long new_Fr__SWIG_3(String jarg1, int jarg2);
public final static native long new_Fr__SWIG_4(String jarg1);
public final static native boolean Fr_equals(long jarg1, Fr jarg1_, long jarg2, Fr jarg2_);
public final static native boolean Fr_isZero(long jarg1, Fr jarg1_);
public final static native boolean Fr_isOne(long jarg1, Fr jarg1_);
public final static native void Fr_setStr__SWIG_0(long jarg1, Fr jarg1_, String jarg2, int jarg3);
public final static native void Fr_setStr__SWIG_1(long jarg1, Fr jarg1_, String jarg2);
public final static native void Fr_setInt(long jarg1, Fr jarg1_, int jarg2);
public final static native void Fr_clear(long jarg1, Fr jarg1_);
public final static native void Fr_setByCSPRNG(long jarg1, Fr jarg1_);
public final static native String Fr_toString__SWIG_0(long jarg1, Fr jarg1_, int jarg2);
public final static native String Fr_toString__SWIG_1(long jarg1, Fr jarg1_);
public final static native void Fr_deserialize(long jarg1, Fr jarg1_, byte[] jarg2);
public final static native void Fr_setLittleEndianMod(long jarg1, Fr jarg1_, byte[] jarg2);
public final static native void Fr_setHashOf(long jarg1, Fr jarg1_, byte[] jarg2);
public final static native byte[] Fr_serialize(long jarg1, Fr jarg1_);
public final static native void delete_Fr(long jarg1);
public final static native void neg__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_);
public final static native void inv__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_);
public final static native void add__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native void sub__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native void mul__SWIG_3(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native void div__SWIG_1(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native long new_Fp__SWIG_0();
public final static native long new_Fp__SWIG_1(long jarg1, Fp jarg1_);
public final static native long new_Fp__SWIG_2(int jarg1);
public final static native long new_Fp__SWIG_3(String jarg1, int jarg2);
public final static native long new_Fp__SWIG_4(String jarg1);
public final static native boolean Fp_equals(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_);
public final static native boolean Fp_isZero(long jarg1, Fp jarg1_);
public final static native boolean Fp_isOne(long jarg1, Fp jarg1_);
public final static native void Fp_setStr__SWIG_0(long jarg1, Fp jarg1_, String jarg2, int jarg3);
public final static native void Fp_setStr__SWIG_1(long jarg1, Fp jarg1_, String jarg2);
public final static native void Fp_setInt(long jarg1, Fp jarg1_, int jarg2);
public final static native void Fp_clear(long jarg1, Fp jarg1_);
public final static native void Fp_setByCSPRNG(long jarg1, Fp jarg1_);
public final static native String Fp_toString__SWIG_0(long jarg1, Fp jarg1_, int jarg2);
public final static native String Fp_toString__SWIG_1(long jarg1, Fp jarg1_);
public final static native void Fp_deserialize(long jarg1, Fp jarg1_, byte[] jarg2);
public final static native byte[] Fp_serialize(long jarg1, Fp jarg1_);
public final static native void delete_Fp(long jarg1);
public final static native void neg__SWIG_2(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_);
public final static native void dbl__SWIG_0(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_);
public final static native void add__SWIG_2(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_, long jarg3, G1 jarg3_);
public final static native void sub__SWIG_2(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_, long jarg3, G1 jarg3_);
public final static native void pairing(long jarg1, GT jarg1_, long jarg2, G1 jarg2_, long jarg3, G2 jarg3_);
public final static native void hashAndMapToG1(long jarg1, G1 jarg1_, byte[] jarg2);
public final static native long new_G1__SWIG_0();
public final static native long new_G1__SWIG_1(long jarg1, G1 jarg1_);
public final static native long new_G1__SWIG_2(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_);
public final static native boolean G1_equals(long jarg1, G1 jarg1_, long jarg2, G1 jarg2_);
public final static native boolean G1_isZero(long jarg1, G1 jarg1_);
public final static native boolean G1_isValidOrder(long jarg1, G1 jarg1_);
public final static native void G1_set(long jarg1, G1 jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_);
public final static native void G1_clear(long jarg1, G1 jarg1_);
public final static native void G1_setStr__SWIG_0(long jarg1, G1 jarg1_, String jarg2, int jarg3);
public final static native void G1_setStr__SWIG_1(long jarg1, G1 jarg1_, String jarg2);
public final static native String G1_toString__SWIG_0(long jarg1, G1 jarg1_, int jarg2);
public final static native String G1_toString__SWIG_1(long jarg1, G1 jarg1_);
public final static native void G1_deserialize(long jarg1, G1 jarg1_, byte[] jarg2);
public final static native byte[] G1_serialize(long jarg1, G1 jarg1_);
public final static native void delete_G1(long jarg1);
public final static native void neg__SWIG_3(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_);
public final static native void dbl__SWIG_1(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_);
public final static native void add__SWIG_3(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_, long jarg3, G2 jarg3_);
public final static native void sub__SWIG_3(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_, long jarg3, G2 jarg3_);
public final static native void hashAndMapToG2(long jarg1, G2 jarg1_, byte[] jarg2);
public final static native long new_G2__SWIG_0();
public final static native long new_G2__SWIG_1(long jarg1, G2 jarg1_);
public final static native long new_G2__SWIG_2(long jarg1, Fp jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_, long jarg4, Fp jarg4_);
public final static native boolean G2_equals(long jarg1, G2 jarg1_, long jarg2, G2 jarg2_);
public final static native boolean G2_isZero(long jarg1, G2 jarg1_);
public final static native void G2_set(long jarg1, G2 jarg1_, long jarg2, Fp jarg2_, long jarg3, Fp jarg3_, long jarg4, Fp jarg4_, long jarg5, Fp jarg5_);
public final static native void G2_clear(long jarg1, G2 jarg1_);
public final static native void G2_setStr__SWIG_0(long jarg1, G2 jarg1_, String jarg2, int jarg3);
public final static native void G2_setStr__SWIG_1(long jarg1, G2 jarg1_, String jarg2);
public final static native String G2_toString__SWIG_0(long jarg1, G2 jarg1_, int jarg2);
public final static native String G2_toString__SWIG_1(long jarg1, G2 jarg1_);
public final static native void G2_deserialize(long jarg1, G2 jarg1_, byte[] jarg2);
public final static native byte[] G2_serialize(long jarg1, G2 jarg1_);
public final static native void delete_G2(long jarg1);
public final static native void mul__SWIG_4(long jarg1, GT jarg1_, long jarg2, GT jarg2_, long jarg3, GT jarg3_);
public final static native void inv__SWIG_2(long jarg1, GT jarg1_, long jarg2, GT jarg2_);
public final static native long new_GT__SWIG_0();
public final static native long new_GT__SWIG_1(long jarg1, GT jarg1_);
public final static native boolean GT_equals(long jarg1, GT jarg1_, long jarg2, GT jarg2_);
public final static native boolean GT_isOne(long jarg1, GT jarg1_);
public final static native void GT_clear(long jarg1, GT jarg1_);
public final static native void GT_setStr__SWIG_0(long jarg1, GT jarg1_, String jarg2, int jarg3);
public final static native void GT_setStr__SWIG_1(long jarg1, GT jarg1_, String jarg2);
public final static native String GT_toString__SWIG_0(long jarg1, GT jarg1_, int jarg2);
public final static native String GT_toString__SWIG_1(long jarg1, GT jarg1_);
public final static native void GT_deserialize(long jarg1, GT jarg1_, byte[] jarg2);
public final static native byte[] GT_serialize(long jarg1, GT jarg1_);
public final static native void delete_GT(long jarg1);
}

@ -0,0 +1,87 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class PrivateKey {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected PrivateKey(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(PrivateKey obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
ElgamalJNI.delete_PrivateKey(swigCPtr);
}
swigCPtr = 0;
}
}
public String toStr() {
return ElgamalJNI.PrivateKey_toStr(swigCPtr, this);
}
public String toString() {
return ElgamalJNI.PrivateKey_toString(swigCPtr, this);
}
public void fromStr(String str) {
ElgamalJNI.PrivateKey_fromStr(swigCPtr, this, str);
}
public void save(String fileName) {
ElgamalJNI.PrivateKey_save(swigCPtr, this, fileName);
}
public void load(String fileName) {
ElgamalJNI.PrivateKey_load(swigCPtr, this, fileName);
}
public void init() {
ElgamalJNI.PrivateKey_init(swigCPtr, this);
}
public PublicKey getPublicKey() {
return new PublicKey(ElgamalJNI.PrivateKey_getPublicKey(swigCPtr, this), true);
}
public int dec(CipherText c, SWIGTYPE_p_bool b) {
return ElgamalJNI.PrivateKey_dec__SWIG_0(swigCPtr, this, CipherText.getCPtr(c), c, SWIGTYPE_p_bool.getCPtr(b));
}
public int dec(CipherText c) {
return ElgamalJNI.PrivateKey_dec__SWIG_1(swigCPtr, this, CipherText.getCPtr(c), c);
}
public void setCache(int rangeMin, int rangeMax) {
ElgamalJNI.PrivateKey_setCache(swigCPtr, this, rangeMin, rangeMax);
}
public void clearCache() {
ElgamalJNI.PrivateKey_clearCache(swigCPtr, this);
}
public PrivateKey() {
this(ElgamalJNI.new_PrivateKey(), true);
}
}

@ -0,0 +1,83 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class PublicKey {
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected PublicKey(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(PublicKey obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
ElgamalJNI.delete_PublicKey(swigCPtr);
}
swigCPtr = 0;
}
}
public String toStr() {
return ElgamalJNI.PublicKey_toStr(swigCPtr, this);
}
public String toString() {
return ElgamalJNI.PublicKey_toString(swigCPtr, this);
}
public void fromStr(String str) {
ElgamalJNI.PublicKey_fromStr(swigCPtr, this, str);
}
public void save(String fileName) {
ElgamalJNI.PublicKey_save(swigCPtr, this, fileName);
}
public void load(String fileName) {
ElgamalJNI.PublicKey_load(swigCPtr, this, fileName);
}
public void enc(CipherText c, int m) {
ElgamalJNI.PublicKey_enc__SWIG_0(swigCPtr, this, CipherText.getCPtr(c), c, m);
}
public void enc(CipherText c, String str) {
ElgamalJNI.PublicKey_enc__SWIG_1(swigCPtr, this, CipherText.getCPtr(c), c, str);
}
public void rerandomize(CipherText c) {
ElgamalJNI.PublicKey_rerandomize(swigCPtr, this, CipherText.getCPtr(c), c);
}
public void add(CipherText c, int m) {
ElgamalJNI.PublicKey_add__SWIG_0(swigCPtr, this, CipherText.getCPtr(c), c, m);
}
public void add(CipherText c, String str) {
ElgamalJNI.PublicKey_add__SWIG_1(swigCPtr, this, CipherText.getCPtr(c), c, str);
}
public PublicKey() {
this(ElgamalJNI.new_PublicKey(), true);
}
}

@ -0,0 +1,26 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.2
*
* Do not make changes to this file unless you know what you are doing--modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
package com.herumi.mcl;
public class SWIGTYPE_p_bool {
private transient long swigCPtr;
protected SWIGTYPE_p_bool(long cPtr, @SuppressWarnings("unused") boolean futureUse) {
swigCPtr = cPtr;
}
protected SWIGTYPE_p_bool() {
swigCPtr = 0;
}
protected static long getCPtr(SWIGTYPE_p_bool obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
}

@ -13,6 +13,11 @@ typedef mcl::FpT<mcl::ZnTag, 521> Zn;
typedef mcl::EcT<Fp> Ec;
typedef mcl::ElgamalT<Ec, Zn> Elgamal;
#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
#endif
/*
init system
@param param [in] string such as "ecParamName hashName"
@ -29,11 +34,11 @@ void SystemInit(const std::string& param) throw(std::exception)
if (iss >> ecParamStr >> hashNameStr) {
Param& p = Param::getParam();
p.ecParam = mcl::getEcParam(ecParamStr);
Zn::init(p.ecParam->n);
Fp::init(p.ecParam->p);
Ec::init(p.ecParam->a, p.ecParam->b);
p.hashName = cybozu::crypto::Hash::getName(hashNameStr);
return;
if (p.ecParam) {
mcl::initCurve<Ec, Zn>(p.ecParam->curveType);
p.hashName = cybozu::crypto::Hash::getName(hashNameStr);
return;
}
}
throw cybozu::Exception("SystemInit:bad param") << param;
}
@ -145,3 +150,7 @@ public:
self_.clearCache();
}
};
#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 3.0.12
* Version 4.0.2
*
* This file is not intended to be easily readable and contains a number of
* coding conventions designed to improve portability and efficiency. Do not make
@ -182,15 +182,16 @@ template <typename T> T SwigValueInit() {
/* Support for throwing Java exceptions */
typedef enum {
SWIG_JavaOutOfMemoryError = 1,
SWIG_JavaIOException,
SWIG_JavaRuntimeException,
SWIG_JavaOutOfMemoryError = 1,
SWIG_JavaIOException,
SWIG_JavaRuntimeException,
SWIG_JavaIndexOutOfBoundsException,
SWIG_JavaArithmeticException,
SWIG_JavaIllegalArgumentException,
SWIG_JavaNullPointerException,
SWIG_JavaDirectorPureVirtual,
SWIG_JavaUnknownError
SWIG_JavaUnknownError,
SWIG_JavaIllegalStateException,
} SWIG_JavaExceptionCodes;
typedef struct {
@ -211,6 +212,7 @@ static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionC
{ SWIG_JavaNullPointerException, "java/lang/NullPointerException" },
{ SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" },
{ SWIG_JavaUnknownError, "java/lang/UnknownError" },
{ SWIG_JavaIllegalStateException, "java/lang/IllegalStateException" },
{ (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" }
};
const SWIG_JavaExceptions_t *except_ptr = java_exceptions;
@ -358,12 +360,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_SystemInit(JNIEnv *jenv,
jenv->ReleaseStringUTFChars(jarg1, arg1_pstr);
try {
SystemInit((std::string const &)*arg1);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -378,12 +378,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toStr(JNIE
arg1 = *(CipherText **)&jarg1;
try {
result = ((CipherText const *)arg1)->toStr();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -400,12 +398,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1toString(J
arg1 = *(CipherText **)&jarg1;
try {
result = ((CipherText const *)arg1)->toString();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -430,12 +426,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1fromStr(JNIEn
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->fromStr((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -455,12 +449,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1add(JNIEnv *j
}
try {
(arg1)->add((CipherText const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -475,12 +467,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_1
arg2 = (int)jarg2;
try {
(arg1)->mul(arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -503,12 +493,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_CipherText_1mul_1_1SWIG_1
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->mul((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -545,12 +533,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toStr(JNIEn
arg1 = *(PublicKey **)&jarg1;
try {
result = ((PublicKey const *)arg1)->toStr();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -567,12 +553,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1toString(JN
arg1 = *(PublicKey **)&jarg1;
try {
result = ((PublicKey const *)arg1)->toString();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -597,12 +581,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1fromStr(JNIEnv
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->fromStr((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -625,12 +607,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1save(JNIEnv *j
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
((PublicKey const *)arg1)->save((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -653,12 +633,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1load(JNIEnv *j
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->load((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -680,12 +658,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_10
arg3 = (int)jarg3;
try {
((PublicKey const *)arg1)->enc(*arg2,arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -715,12 +691,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1enc_1_1SWIG_11
jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
try {
((PublicKey const *)arg1)->enc(*arg2,(std::string const &)*arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -740,12 +714,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1rerandomize(JN
}
try {
((PublicKey const *)arg1)->rerandomize(*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -767,12 +739,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_10
arg3 = (int)jarg3;
try {
((PublicKey const *)arg1)->add(*arg2,arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -802,12 +772,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PublicKey_1add_1_1SWIG_11
jenv->ReleaseStringUTFChars(jarg3, arg3_pstr);
try {
((PublicKey const *)arg1)->add(*arg2,(std::string const &)*arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -844,12 +812,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toStr(JNIE
arg1 = *(PrivateKey **)&jarg1;
try {
result = ((PrivateKey const *)arg1)->toStr();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -866,12 +832,10 @@ SWIGEXPORT jstring JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1toString(J
arg1 = *(PrivateKey **)&jarg1;
try {
result = ((PrivateKey const *)arg1)->toString();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = jenv->NewStringUTF((&result)->c_str());
return jresult;
}
@ -896,12 +860,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1fromStr(JNIEn
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->fromStr((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -924,12 +886,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1save(JNIEnv *
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
((PrivateKey const *)arg1)->save((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -952,12 +912,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1load(JNIEnv *
jenv->ReleaseStringUTFChars(jarg2, arg2_pstr);
try {
(arg1)->load((std::string const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -970,12 +928,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1init(JNIEnv *
arg1 = *(PrivateKey **)&jarg1;
try {
(arg1)->init();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -990,12 +946,10 @@ SWIGEXPORT jlong JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1getPublicKey
arg1 = *(PrivateKey **)&jarg1;
try {
result = ((PrivateKey const *)arg1)->getPublicKey();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
*(PublicKey **)&jresult = new PublicKey((const PublicKey &)result);
return jresult;
}
@ -1021,12 +975,10 @@ SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_1
arg3 = *(bool **)&jarg3;
try {
result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2,arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = (jint)result;
return jresult;
}
@ -1050,12 +1002,10 @@ SWIGEXPORT jint JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1dec_1_1SWIG_1
}
try {
result = (int)((PrivateKey const *)arg1)->dec((CipherText const &)*arg2);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return 0;
}
jresult = (jint)result;
return jresult;
}
@ -1074,12 +1024,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1setCache(JNIE
arg3 = (int)jarg3;
try {
(arg1)->setCache(arg2,arg3);
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}
@ -1092,12 +1040,10 @@ SWIGEXPORT void JNICALL Java_com_herumi_mcl_ElgamalJNI_PrivateKey_1clearCache(JN
arg1 = *(PrivateKey **)&jarg1;
try {
(arg1)->clearCache();
}
catch(std::exception &_e) {
} catch(std::exception &_e) {
SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, (&_e)->what());
return ;
}
}

@ -1,13 +1,14 @@
# JNI for mcl (experimental)
This library provides functionality to compute the optimal ate pairing
over Barreto-Naehrig (BN) curves.
over Barreto-Naehrig (BN) or BLS12-381 curves.
# Initialization
Load the library `mcl_bn256`.
Load the library `mcljava`.
```
import com.herumi.mcl.*;
System.loadLibrary("mcl_bn256");
System.loadLibrary(System.mapLibraryName("mcljava"));
Mcl.SystemInit(curveType); // curveType = Mcl.BN254 or Mcl.BLS12_381
```
# Classes
@ -21,75 +22,67 @@ System.loadLibrary("mcl_bn256");
## Fr
* `Fr::setInt(int x)` ; set by x
* `Fr::setStr(String str)` ; set by str such as "123", "0xfff", etc.
* `Fr::setRand()` ; randomly set
* `Bn256.neg(Fr y, Fr x)` ; `y = -x`
* `Bn256.add(Fr z, Fr x, Fr y)` ; `z = x + y`
* `Bn256.sub(Fr z, Fr x, Fr y)` ; `z = x - y`
* `Bn256.mul(Fr z, Fr x, Fr y)` ; `z = x * y`
* `Bn256.div(Fr z, Fr x, Fr y)` ; `z = x / y`
* `Fr::setByCSPRNG()` ; randomly set
* `Mcl.neg(Fr y, Fr x)` ; `y = -x`
* `Mcl.add(Fr z, Fr x, Fr y)` ; `z = x + y`
* `Mcl.sub(Fr z, Fr x, Fr y)` ; `z = x - y`
* `Mcl.mul(Fr z, Fr x, Fr y)` ; `z = x * y`
* `Mcl.div(Fr z, Fr x, Fr y)` ; `z = x / y`
## G1
* `G1::set(String x, String y)` ; set by (x, y)
* `G1::hashAndMapToG1(String m)` ; take SHA-256 of m and map it to an element of G1
* `G1::setStr(String str)` ; set by the result of `toString()` method
* `Bn256.neg(G1 y, G1 x)` ; `y = -x`
* `Bn256.dbl(G1 y, G1 x)` ; `y = 2x`
* `Bn256.add(G1 z, G1 x, G1 y)` ; `z = x + y`
* `Bn256.sub(G1 z, G1 x, G1 y)` ; `z = x - y`
* `Bn256.mul(G1 z, G1 x, Fr y)` ; `z = x * y`
* `Mcl.neg(G1 y, G1 x)` ; `y = -x`
* `Mcl.dbl(G1 y, G1 x)` ; `y = 2x`
* `Mcl.add(G1 z, G1 x, G1 y)` ; `z = x + y`
* `Mcl.sub(G1 z, G1 x, G1 y)` ; `z = x - y`
* `Mcl.mul(G1 z, G1 x, Fr y)` ; `z = x * y`
## G2
* `G2::set(String xa, String xb, String ya, String yb)` ; set by ((xa, xb), (ya, yb))
* `G2::setStr(String str)` ; set by the result of `toString()` method
* `Bn256.neg(G2 y, G2 x)` ; `y = -x`
* `Bn256.dbl(G2 y, G2 x)` ; `y = 2x`
* `Bn256.add(G2 z, G2 x, G2 y)` ; `z = x + y`
* `Bn256.sub(G2 z, G2 x, G2 y)` ; `z = x - y`
* `Bn256.mul(G2 z, G2 x, Fr y)` ; `z = x * y`
* `Mcl.neg(G2 y, G2 x)` ; `y = -x`
* `Mcl.dbl(G2 y, G2 x)` ; `y = 2x`
* `Mcl.add(G2 z, G2 x, G2 y)` ; `z = x + y`
* `Mcl.sub(G2 z, G2 x, G2 y)` ; `z = x - y`
* `Mcl.mul(G2 z, G2 x, Fr y)` ; `z = x * y`
## GT
* `GT::setStr(String str)` ; set by the result of `toString()` method
* `Bn256.mul(GT z, GT x, GT y)` ; `z = x * y`
* `Bn256.pow(GT z, GT x, Fr y)` ; `z = x ^ y`
* `Mcl.mul(GT z, GT x, GT y)` ; `z = x * y`
* `Mcl.pow(GT z, GT x, Fr y)` ; `z = x ^ y`
* `Mcl.inv(GT y, GT x)` ; `y = x^{-1}`
## pairing
* `Bn256.pairing(GT e, G1 P, G2 Q)` ; e = e(P, Q)
* `Mcl.pairing(GT e, G1 P, G2 Q)` ; e = e(P, Q)
# BLS signature sample
```
String xa = "12723517038133731887338407189719511622662176727675373276651903807414909099441";
String xb = "4168783608814932154536427934509895782246573715297911553964171371032945126671";
String ya = "13891744915211034074451795021214165905772212241412891944830863846330766296736";
String yb = "7937318970632701341203597196594272556916396164729705624521405069090520231616";
G2 Q = new G2(xa, xb, ya, yb); // fixed point of G2
G2 Q = new G2();
Mcl.hashAndMapToG2(Q, "abc".getBytes());
Fr s = new Fr();
s.setRand(); // secret key
s.setByCSPRNG(); // secret key
G2 pub = new G2();
Bn256.mul(pub, Q, s); // public key = sQ
Mcl.mul(pub, Q, s); // public key = sQ
String m = "signature test";
G1 H = new G1();
H.hashAndMapToG1(m); // H = Hash(m)
Mcl.hashAndMapToG1(H, m.getBytes()); // H = Hash(m)
G1 sign = new G1();
Bn256.mul(sign, H, s); // signature of m = s H
Mcl.mul(sign, H, s); // signature of m = s H
GT e1 = new GT();
GT e2 = new GT();
Bn256.pairing(e1, H, pub); // e1 = e(H, s Q)
Bn256.pairing(e2, sign, Q); // e2 = e(s H, Q);
Mcl.pairing(e1, H, pub); // e1 = e(H, s Q)
Mcl.pairing(e2, sign, Q); // e2 = e(s H, Q);
assertBool("verify signature", e1.equals(e2));
```
# Make test
```
cd java
make test_bn256
cd ffi/java
make test
```
# Sample code
[Bn256Test.java](https://github.com/herumi/mcl/blob/master/java/Bn256Test.java)
[MclTest.java](https://github.com/herumi/mcl/blob/master/ffi/java/MclTest.java)

@ -5,9 +5,11 @@ set SWIG=..\..\..\..\p\swig\swig.exe
set PACKAGE_NAME=com.herumi.mcl
set PACKAGE_DIR=%PACKAGE_NAME:.=\%
if /i "%1"=="" (
set NAME=elgamal
set NAME=mcl
set LIBNAME=
) else (
set NAME=%1
set LIBNAME=%NAME%
)
echo [[run swig]]
@ -15,7 +17,7 @@ mkdir %PACKAGE_DIR%
set TOP_DIR=../..
%SWIG% -java -package %PACKAGE_NAME% -outdir %PACKAGE_DIR% -c++ -Wall %NAME%.i
echo [[make dll]]
cl /MT /DNOMINMAX /LD /Ox /DNDEBUG /EHsc %NAME%_wrap.cxx %TOP_DIR%/src/fp.cpp -DMCL_NO_AUTOLINK -I%JAVA_INCLUDE% -I%JAVA_INCLUDE%\win32 -I%TOP_DIR%/include -I%TOP_DIR%/../cybozulib/include -I%TOP_DIR%/../cybozulib_ext/include -I%TOP_DIR%/../xbyak /link /LIBPATH:%TOP_DIR%/../cybozulib_ext/lib /OUT:%TOP_DIR%/bin/mcl_%NAME%.dll
cl /MT /DNOMINMAX /LD /Ox /DNDEBUG /EHsc %NAME%_wrap.cxx %TOP_DIR%/src/fp.cpp -DMCL_NO_AUTOLINK -I%JAVA_INCLUDE% -I%JAVA_INCLUDE%\win32 -I%TOP_DIR%/include -I%TOP_DIR%/../cybozulib/include -I%TOP_DIR%/../cybozulib_ext/include -I%TOP_DIR%/../xbyak /link /LIBPATH:%TOP_DIR%/../cybozulib_ext/lib /OUT:%TOP_DIR%/bin/mcl%LIBNAME%java.dll
call run-%NAME%.bat

@ -0,0 +1,29 @@
%module Mcl
%include "std_string.i"
%include "std_except.i"
%apply(char *STRING, size_t LENGTH) { (const char *cbuf, size_t bufSize) };
%{
#include <mcl/bls12_381.hpp>
#include "mcl_impl.hpp"
%}
%typemap(jtype) void serialize "byte[]"
%typemap(jstype) void serialize "byte[]"
%typemap(jni) void serialize "jbyteArray"
%typemap(javaout) void serialize { return $jnicall; }
%typemap(in, numinputs=0) std::string& out (std::string buf) "$1=&buf;"
%typemap(argout) std::string& out {
$result = JCALL1(NewByteArray, jenv, $1->size());
JCALL4(SetByteArrayRegion, jenv, $result, 0, $1->size(), (const jbyte*)$1->c_str());
}
%include "mcl_impl.hpp"
%javaconst(1);
#define BN254 0
#define BLS12_381 5

@ -0,0 +1,436 @@
#include <mcl/bls12_381.hpp>
#include <stdint.h>
#include <sstream>
#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
#endif
void SystemInit(int curveType) throw(std::exception)
{
mcl::CurveParam cp;
switch (curveType) {
case MCL_BN254: cp = mcl::BN254; break;
case MCL_BN_SNARK1: cp = mcl::BN_SNARK1; break;
case MCL_BLS12_381: cp = mcl::BLS12_381; break;
default:
throw std::runtime_error("bad curveType");
}
mcl::bn::initPairing(cp);
}
template<class T>
void deserializeT(T& x, const char *cbuf, size_t bufSize)
{
if (x.deserialize(cbuf, bufSize) == 0) {
throw std::runtime_error("deserialize");
}
}
template<class T>
void setLittleEndianModT(T& x, const char *cbuf, size_t bufSize)
{
x.setLittleEndianMod(cbuf, bufSize);
}
template<class T>
void setHashOfT(T& x, const char *cbuf, size_t bufSize)
{
x.setHashOf(cbuf, bufSize);
}
template<class T>
void serializeT(std::string& out, const T& x)
{
out.resize(48 * 12);
size_t n = x.serialize(&out[0], out.size());
if (n == 0) throw std::runtime_error("serializeT");
out.resize(n);
}
class G1;
class G2;
class GT;
/*
Fr = Z / rZ
*/
class Fr {
mcl::bn::Fr self_;
friend class G1;
friend class G2;
friend class GT;
friend void neg(Fr& y, const Fr& x);
friend void inv(Fr& y, const Fr& x);
friend void add(Fr& z, const Fr& x, const Fr& y);
friend void sub(Fr& z, const Fr& x, const Fr& y);
friend void mul(Fr& z, const Fr& x, const Fr& y);
friend void mul(G1& z, const G1& x, const Fr& y);
friend void mul(G2& z, const G2& x, const Fr& y);
friend void div(Fr& z, const Fr& x, const Fr& y);
friend void pow(GT& z, const GT& x, const Fr& y);
public:
Fr() {}
Fr(const Fr& rhs) : self_(rhs.self_) {}
Fr(int x) : self_(x) {}
Fr(const std::string& str, int base = 0) throw(std::exception)
: self_(str, base) {}
bool equals(const Fr& rhs) const { return self_ == rhs.self_; }
bool isZero() const { return self_.isZero(); }
bool isOne() const { return self_.isOne(); }
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
void setInt(int x)
{
self_ = x;
}
void clear()
{
self_.clear();
}
void setByCSPRNG()
{
self_.setByCSPRNG();
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void setLittleEndianMod(const char *cbuf, size_t bufSize) throw(std::exception)
{
setLittleEndianModT(self_, cbuf, bufSize);
}
void setHashOf(const char *cbuf, size_t bufSize) throw(std::exception)
{
setHashOfT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void neg(Fr& y, const Fr& x)
{
mcl::bn::Fr::neg(y.self_, x.self_);
}
void inv(Fr& y, const Fr& x)
{
mcl::bn::Fr::inv(y.self_, x.self_);
}
void add(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn::Fr::add(z.self_, x.self_, y.self_);
}
void sub(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn::Fr::sub(z.self_, x.self_, y.self_);
}
void mul(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn::Fr::mul(z.self_, x.self_, y.self_);
}
void div(Fr& z, const Fr& x, const Fr& y)
{
mcl::bn::Fr::div(z.self_, x.self_, y.self_);
}
class Fp {
mcl::bn::Fp self_;
friend class G1;
friend class G2;
friend class GT;
friend void neg(Fp& y, const Fp& x);
friend void inv(Fp& y, const Fp& x);
friend void add(Fp& z, const Fp& x, const Fp& y);
friend void sub(Fp& z, const Fp& x, const Fp& y);
friend void mul(Fp& z, const Fp& x, const Fp& y);
friend void div(Fp& z, const Fp& x, const Fp& y);
public:
Fp() {}
Fp(const Fp& rhs) : self_(rhs.self_) {}
Fp(int x) : self_(x) {}
Fp(const std::string& str, int base = 0) throw(std::exception)
: self_(str, base) {}
bool equals(const Fp& rhs) const { return self_ == rhs.self_; }
bool isZero() const { return self_.isZero(); }
bool isOne() const { return self_.isOne(); }
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
void setInt(int x)
{
self_ = x;
}
void clear()
{
self_.clear();
}
void setByCSPRNG()
{
self_.setByCSPRNG();
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void neg(Fp& y, const Fp& x)
{
mcl::bn::Fp::neg(y.self_, x.self_);
}
void inv(Fp& y, const Fp& x)
{
mcl::bn::Fp::inv(y.self_, x.self_);
}
void add(Fp& z, const Fp& x, const Fp& y)
{
mcl::bn::Fp::add(z.self_, x.self_, y.self_);
}
void sub(Fp& z, const Fp& x, const Fp& y)
{
mcl::bn::Fp::sub(z.self_, x.self_, y.self_);
}
void mul(Fp& z, const Fp& x, const Fp& y)
{
mcl::bn::Fp::mul(z.self_, x.self_, y.self_);
}
void div(Fp& z, const Fp& x, const Fp& y)
{
mcl::bn::Fp::div(z.self_, x.self_, y.self_);
}
/*
#G1 = r
*/
class G1 {
mcl::bn::G1 self_;
friend void neg(G1& y, const G1& x);
friend void dbl(G1& y, const G1& x);
friend void add(G1& z, const G1& x, const G1& y);
friend void sub(G1& z, const G1& x, const G1& y);
friend void mul(G1& z, const G1& x, const Fr& y);
friend void pairing(GT& e, const G1& P, const G2& Q);
friend void hashAndMapToG1(G1& P, const char *cbuf, size_t bufSize) throw(std::exception);
public:
G1() {}
G1(const G1& rhs) : self_(rhs.self_) {}
G1(const Fp& x, const Fp& y) throw(std::exception)
: self_(x.self_, y.self_) { }
bool equals(const G1& rhs) const { return self_ == rhs.self_; }
bool isZero() const { return self_.isZero(); }
bool isValidOrder() const { return self_.isValidOrder(); }
void set(const Fp& x, const Fp& y) throw(std::exception)
{
self_.set(x.self_, y.self_);
}
void clear()
{
self_.clear();
}
/*
compressed format
*/
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void neg(G1& y, const G1& x)
{
mcl::bn::G1::neg(y.self_, x.self_);
}
void dbl(G1& y, const G1& x)
{
mcl::bn::G1::dbl(y.self_, x.self_);
}
void add(G1& z, const G1& x, const G1& y)
{
mcl::bn::G1::add(z.self_, x.self_, y.self_);
}
void sub(G1& z, const G1& x, const G1& y)
{
mcl::bn::G1::sub(z.self_, x.self_, y.self_);
}
void mul(G1& z, const G1& x, const Fr& y)
{
mcl::bn::G1::mul(z.self_, x.self_, y.self_);
}
/*
#G2 = r
*/
class G2 {
mcl::bn::G2 self_;
friend void neg(G2& y, const G2& x);
friend void dbl(G2& y, const G2& x);
friend void add(G2& z, const G2& x, const G2& y);
friend void sub(G2& z, const G2& x, const G2& y);
friend void mul(G2& z, const G2& x, const Fr& y);
friend void pairing(GT& e, const G1& P, const G2& Q);
friend void hashAndMapToG2(G2& P, const char *cbuf, size_t bufSize) throw(std::exception);
public:
G2() {}
G2(const G2& rhs) : self_(rhs.self_) {}
G2(const Fp& ax, const Fp& ay, const Fp& bx, const Fp& by) throw(std::exception)
: self_(mcl::bn::Fp2(ax.self_, ay.self_), mcl::bn::Fp2(bx.self_, by.self_))
{
}
bool equals(const G2& rhs) const { return self_ == rhs.self_; }
bool isZero() const { return self_.isZero(); }
void set(const Fp& ax, const Fp& ay, const Fp& bx, const Fp& by) throw(std::exception)
{
self_.set(mcl::bn::Fp2(ax.self_, ay.self_), mcl::bn::Fp2(bx.self_, by.self_));
}
void clear()
{
self_.clear();
}
/*
compressed format
*/
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void neg(G2& y, const G2& x)
{
mcl::bn::G2::neg(y.self_, x.self_);
}
void dbl(G2& y, const G2& x)
{
mcl::bn::G2::dbl(y.self_, x.self_);
}
void add(G2& z, const G2& x, const G2& y)
{
mcl::bn::G2::add(z.self_, x.self_, y.self_);
}
void sub(G2& z, const G2& x, const G2& y)
{
mcl::bn::G2::sub(z.self_, x.self_, y.self_);
}
void mul(G2& z, const G2& x, const Fr& y)
{
mcl::bn::G2::mul(z.self_, x.self_, y.self_);
}
/*
#GT = r
*/
class GT {
mcl::bn::Fp12 self_;
friend void mul(GT& z, const GT& x, const GT& y);
friend void inv(GT& y, GT& x);
friend void pow(GT& z, const GT& x, const Fr& y);
friend void pairing(GT& e, const G1& P, const G2& Q);
public:
GT() {}
GT(const GT& rhs) : self_(rhs.self_) {}
bool equals(const GT& rhs) const { return self_ == rhs.self_; }
bool isOne() const { return self_.isOne(); }
void clear()
{
self_.clear();
}
void setStr(const std::string& str, int base = 0) throw(std::exception)
{
self_.setStr(str, base);
}
std::string toString(int base = 0) const throw(std::exception)
{
return self_.getStr(base);
}
void deserialize(const char *cbuf, size_t bufSize) throw(std::exception)
{
deserializeT(self_, cbuf, bufSize);
}
void serialize(std::string& out) const throw(std::exception)
{
serializeT(out, self_);
}
};
void mul(GT& z, const GT& x, const GT& y)
{
mcl::bn::Fp12::mul(z.self_, x.self_, y.self_);
}
void inv(GT& y, GT& x)
{
mcl::bn::Fp12::unitaryInv(y.self_, x.self_);
}
void pow(GT& z, const GT& x, const Fr& y)
{
mcl::bn::Fp12::pow(z.self_, x.self_, y.self_);
}
void pairing(GT& e, const G1& P, const G2& Q)
{
mcl::bn::pairing(e.self_, P.self_, Q.self_);
}
void hashAndMapToG1(G1& P, const char *cbuf, size_t bufSize) throw(std::exception)
{
mcl::bn::hashAndMapToG1(P.self_, cbuf, bufSize);
}
void hashAndMapToG2(G2& P, const char *cbuf, size_t bufSize) throw(std::exception)
{
mcl::bn::hashAndMapToG2(P.self_, cbuf, bufSize);
}
#if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif

File diff suppressed because it is too large Load Diff

@ -1,9 +0,0 @@
@echo off
echo [[compile Bn256Test.java]]
%JAVA_DIR%\bin\javac Bn256Test.java
echo [[run Bn256Test]]
set TOP_DIR=..\..
pushd %TOP_DIR%\bin
%JAVA_DIR%\bin\java -classpath ../ffi/java Bn256Test %1 %2 %3 %4 %5 %6
popd

@ -0,0 +1,9 @@
@echo off
echo [[compile MclTest.java]]
%JAVA_DIR%\bin\javac MclTest.java
echo [[run MclTest]]
set TOP_DIR=..\..
pushd %TOP_DIR%\bin
%JAVA_DIR%\bin\java -classpath ../ffi/java MclTest %1 %2 %3 %4 %5 %6
popd

@ -0,0 +1,9 @@
include ../../common.mk
SHE384_256_SLIB=libmclshe384_256.$(LIB_SUF)
she_test: ../../lib/$(SHE384_256_SLIB)
cd ../../lib && env LD_LIBRARY_PATH=./ python3 ../ffi/python/she.py
../../lib/$(SHE384_256_SLIB):
make -C ../../ lib/$(SHE384_256_SLIB)

@ -0,0 +1,7 @@
# sample for Python
## SHE
```
make she_test
```

@ -1,6 +1,7 @@
import os
import platform
from ctypes import *
#from ctypes.util import find_library
BN254 = 0
BLS12_381 = 5
@ -34,6 +35,7 @@ def init(curveType=BN254):
libName = 'mclshe384_256.dll'
else:
raise RuntimeError("not support yet", name)
# lib = cdll.LoadLibrary(find_library(libName))
lib = cdll.LoadLibrary(libName)
ret = lib.sheInit(curveType, MCLBN_COMPILED_TIME_VAR)
if ret != 0:

@ -7,7 +7,6 @@
*/
#include <memory.h>
#include <limits.h>
#include <limits>
#include <cybozu/exception.hpp>
@ -173,7 +172,7 @@ public:
}
inline operator int() const
{
return atoi_local::convertToInt<int>(b_, p_, size_, "2147483648", INT_MIN, 214748364, '8');
return atoi_local::convertToInt<int>(b_, p_, size_, "2147483648", /*INT_MIN*/-2147483648, 214748364, '8');
}
inline operator unsigned int() const
{
@ -181,7 +180,7 @@ public:
}
inline operator long long() const
{
return atoi_local::convertToInt<long long>(b_, p_, size_, "9223372036854775808", LLONG_MIN, 922337203685477580LL, '8');
return atoi_local::convertToInt<long long>(b_, p_, size_, "9223372036854775808", CYBOZU_LLONG_MIN, 922337203685477580LL, '8');
}
inline operator unsigned long long() const
{

@ -0,0 +1,146 @@
#pragma once
/**
@file
@brief atomic operation
@author MITSUNARI Shigeo(@herumi)
@author MITSUNARI Shigeo
*/
#include <cybozu/inttype.hpp>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <intrin.h>
#else
#include <emmintrin.h>
#endif
namespace cybozu {
namespace atomic_local {
template<size_t S>
struct Tag {};
template<>
struct Tag<4> {
template<class T>
static inline T AtomicAddSub(T *p, T y)
{
#ifdef _WIN32
return (T)_InterlockedExchangeAdd((long*)p, (long)y);
#else
return static_cast<T>(__sync_fetch_and_add(p, y));
#endif
}
template<class T>
static inline T AtomicCompareExchangeSub(T *p, T newValue, T oldValue)
{
#ifdef _WIN32
return (T)_InterlockedCompareExchange((long*)p, (long)newValue, (long)oldValue);
#else
return static_cast<T>(__sync_val_compare_and_swap(p, oldValue, newValue));
#endif
}
template<class T>
static inline T AtomicExchangeSub(T *p, T newValue)
{
#ifdef _WIN32
return (T)_InterlockedExchange((long*)p, (long)newValue);
#else
return static_cast<T>(__sync_lock_test_and_set(p, newValue));
#endif
}
};
template<>
struct Tag<8> {
#if (CYBOZU_OS_BIT == 64)
template<class T>
static inline T AtomicAddSub(T *p, T y)
{
#ifdef _WIN32
return (T)_InterlockedExchangeAdd64((int64_t*)p, (int64_t)y);
#else
return static_cast<T>(__sync_fetch_and_add(p, y));
#endif
}
#endif
template<class T>
static inline T AtomicCompareExchangeSub(T *p, T newValue, T oldValue)
{
#ifdef _WIN32
return (T)_InterlockedCompareExchange64((int64_t*)p, (int64_t)newValue, (int64_t)oldValue);
#else
return static_cast<T>(__sync_val_compare_and_swap(p, oldValue, newValue));
#endif
}
#if (CYBOZU_OS_BIT == 64)
template<class T>
static inline T AtomicExchangeSub(T *p, T newValue)
{
#ifdef _WIN32
return (T)_InterlockedExchange64((int64_t*)p, (int64_t)newValue);
#else
return static_cast<T>(__sync_lock_test_and_set(p, newValue));
#endif
}
#endif
};
} // atomic_local
/**
atomic operation
see http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Atomic-Builtins.html
http://msdn.microsoft.com/en-us/library/ms683504(VS.85).aspx
*/
/**
tmp = *p;
*p += y;
return tmp;
*/
template<class T>
T AtomicAdd(T *p, T y)
{
return atomic_local::Tag<sizeof(T)>::AtomicAddSub(p, y);
}
/**
tmp = *p;
if (*p == oldValue) *p = newValue;
return tmp;
*/
template<class T>
T AtomicCompareExchange(T *p, T newValue, T oldValue)
{
return atomic_local::Tag<sizeof(T)>::AtomicCompareExchangeSub(p, newValue, oldValue);
}
/**
tmp = *p;
*p = newValue;
return tmp;
*/
template<class T>
T AtomicExchange(T *p, T newValue)
{
return atomic_local::Tag<sizeof(T)>::AtomicExchangeSub(p, newValue);
}
inline void mfence()
{
#ifdef _MSC_VER
MemoryBarrier();
#else
_mm_mfence();
#endif
}
} // cybozu

@ -42,7 +42,9 @@ public:
#include <errno.h>
#include <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <string.h> // for strerror_r
@ -201,7 +203,6 @@ public:
}
/**
convert NativeErrNo to string(maybe UTF8)
@param err [in] errno
@note Linux : same as ConvertErrorNoToString
Windows : for Win32 API(use en-us)
*/

@ -0,0 +1,626 @@
#pragma once
/**
@file
@brief file class and operations
@author MITSUNARI Shigeo(@herumi)
@remark mingw requires -lshlwapi option
*/
#include <assert.h>
#include <sys/stat.h> // for stat
#include <cybozu/exception.hpp>
#include <vector>
#include <ios>
#ifdef _WIN32
#include <shlwapi.h>
#include <io.h>
#include <fcntl.h>
#include <shlobj.h>
#include <direct.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#ifdef _MSC_VER
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "User32.lib")
#endif
#else
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
namespace cybozu {
class File {
std::string name_; // used for only errmsg
#ifdef _WIN32
typedef HANDLE handleType;
#else
typedef int handleType;
enum {
INVALID_HANDLE_VALUE = -1
};
#endif
handleType hdl_;
bool doClose_;
bool isReadOnly_;
File(const File&);
void operator=(const File&);
#ifdef _WIN32
void openSub()
{
}
#endif
void verifyMode(std::ios::openmode mode)
{
doClose_ = true;
bool isCorrectMode = true;
if (!!(mode & std::ios::in) == !!(mode & std::ios::out)) {
isCorrectMode = false;
} else {
if (mode & std::ios::in) {
isReadOnly_ = true;
if ((mode & std::ios::app) || (mode & std::ios::trunc)) isCorrectMode = false;
} else {
isReadOnly_ = false;
if ((mode & std::ios::app) && (mode & std::ios::trunc)) isCorrectMode = false;
}
}
if (!isCorrectMode) {
throw cybozu::Exception("File:open:bad mode") << name_ << mode;
}
}
#ifdef _WIN32
HANDLE createFile(const std::string& name, DWORD access, DWORD share, DWORD disposition)
{
return ::CreateFileA(name.c_str(), access, share, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL);
}
HANDLE createFile(const std::wstring& name, DWORD access, DWORD share, DWORD disposition)
{
return ::CreateFileW(name.c_str(), access, share, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL);
}
template<class T>
void setHandle(const T& name, std::ios::openmode mode)
{
DWORD access = GENERIC_READ;
DWORD disposition = OPEN_EXISTING;
DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
if (mode & std::ios::out) {
access = GENERIC_WRITE;
disposition = CREATE_ALWAYS;
if (mode & std::ios::app) {
disposition = OPEN_ALWAYS;
}
}
hdl_ = createFile(name, access, share, disposition);
}
#else
void setHandle(const std::string& name, std::ios::openmode mode)
{
int flags = O_RDONLY; // | O_NOATIME; /* can't use on NFS */
mode_t access = 0644;
if (mode & std::ios::out) {
flags = O_WRONLY | O_CREAT;
if (mode & std::ios::app) {
flags |= O_APPEND;
} else {
flags |= O_TRUNC;
}
}
hdl_ = ::open(name.c_str(), flags, access);
}
#endif
template<class T>
void openSub(const T& name, std::ios::openmode mode)
{
if (isOpen()) throw cybozu::Exception("File:open:alread opened") << name_;
verifyMode(mode);
setHandle(name, mode);
if (isOpen()) {
if (mode & std::ios::app) {
seek(getSize(), std::ios::beg);
}
return;
}
throw cybozu::Exception("File:open") << name_ << cybozu::ErrorNo() << static_cast<int>(mode);
}
public:
File()
: hdl_(INVALID_HANDLE_VALUE)
, doClose_(true)
, isReadOnly_(false)
{
}
File(const std::string& name, std::ios::openmode mode)
: hdl_(INVALID_HANDLE_VALUE)
, doClose_(true)
, isReadOnly_(false)
{
open(name, mode);
}
/*
construct with file handle
@param hdl [in] file handle
*/
explicit File(handleType hdl)
: hdl_(hdl)
, doClose_(false)
, isReadOnly_(false)
{
}
~File() CYBOZU_NOEXCEPT
{
if (!doClose_) return;
try {
sync();
close();
} catch (std::exception& e) {
fprintf(stderr, "File:dstr:%s\n", e.what());
} catch (...) {
fprintf(stderr, "File:dstr:unknown\n");
}
}
bool isOpen() const CYBOZU_NOEXCEPT { return hdl_ != INVALID_HANDLE_VALUE; }
/**
support mode
always binary mode
ios::in : read only
ios::out : write only(+truncate)
ios::out + ios::app(append)
*/
void open(const std::string& name, std::ios::openmode mode)
{
name_ = name;
openSub(name, mode);
}
void openW(const std::string& name)
{
open(name, std::ios::out | std::ios::binary | std::ios::trunc);
}
void openR(const std::string& name)
{
open(name, std::ios::in | std::ios::binary);
}
#ifdef _WIN32
void open(const std::wstring& name, std::ios::openmode mode)
{
name_ = cybozu::exception::wstr2str(name);
openSub(name, mode);
}
File(const std::wstring& name, std::ios::openmode mode)
: hdl_(INVALID_HANDLE_VALUE)
{
open(name, mode);
}
void openW(const std::wstring& name)
{
open(name, std::ios::out | std::ios::binary | std::ios::trunc);
}
void openR(const std::wstring& name)
{
open(name, std::ios::in | std::ios::binary);
}
#endif
void close()
{
if (!isOpen()) return;
#ifdef _WIN32
bool isOK = ::CloseHandle(hdl_) != 0;
#else
bool isOK = ::close(hdl_) == 0;
#endif
hdl_ = INVALID_HANDLE_VALUE;
if (isOK) return;
throw cybozu::Exception("File:close") << name_ << cybozu::ErrorNo();
}
/*
sync
@param doFullSync [in] call sync(for only Linux)
*/
void sync(bool doFullSync = false)
{
cybozu::disable_warning_unused_variable(doFullSync);
if (!isOpen()) return;
if (isReadOnly_) return;
#ifdef _WIN32
/* fail if isReadOnly_ */
if (!::FlushFileBuffers(hdl_)) goto ERR_EXIT;
#elif defined(__linux__) || defined(__CYGWIN__)
if (doFullSync) {
if (::fsync(hdl_)) goto ERR_EXIT;
} else {
if (::fdatasync(hdl_)) goto ERR_EXIT;
}
#else
if (::fcntl(hdl_, F_FULLFSYNC)) goto ERR_EXIT;
#endif
return;
ERR_EXIT:
throw cybozu::Exception("File:sync") << name_ << cybozu::ErrorNo();
}
void write(const void *buf, size_t bufSize)
{
const char *p = static_cast<const char *>(buf);
while (bufSize > 0) {
uint32_t size = static_cast<uint32_t>(std::min<size_t>(0x7fffffff, bufSize));
#ifdef _WIN32
DWORD writeSize;
if (!::WriteFile(hdl_, p, size, &writeSize, NULL)) goto ERR_EXIT;
#else
ssize_t writeSize = ::write(hdl_, p, size);
if (writeSize < 0) {
if (errno == EINTR) continue;
goto ERR_EXIT;
}
#endif
p += writeSize;
bufSize -= writeSize;
}
return;
ERR_EXIT:
throw cybozu::Exception("File:write") << name_ << cybozu::ErrorNo();
}
size_t readSome(void *buf, size_t bufSize)
{
uint32_t size = static_cast<uint32_t>(std::min<size_t>(0x7fffffff, bufSize));
#ifdef _WIN32
DWORD readSize;
if (!::ReadFile(hdl_, buf, size, &readSize, NULL)) goto ERR_EXIT;
#else
RETRY:
ssize_t readSize = ::read(hdl_, buf, size);
if (readSize < 0) {
if (errno == EINTR) goto RETRY;
goto ERR_EXIT;
}
#endif
return readSize;
ERR_EXIT:
throw cybozu::Exception("File:read") << name_ << cybozu::ErrorNo();
}
void read(void *buf, size_t bufSize)
{
char *p = static_cast<char *>(buf);
while (bufSize > 0) {
size_t readSize = readSome(p, bufSize);
p += readSize;
bufSize -= readSize;
}
}
void seek(int64_t pos, std::ios::seek_dir dir)
{
#ifdef _WIN32
LARGE_INTEGER largePos;
largePos.QuadPart = pos;
DWORD posMode = FILE_BEGIN;
switch (dir) {
case std::ios::beg:
posMode = FILE_BEGIN;
break;
case std::ios::cur:
default:
posMode = FILE_CURRENT;
break;
case std::ios::end:
posMode = FILE_END;
break;
}
bool isOK = SetFilePointerEx(hdl_, largePos, NULL, posMode) != 0;
#else
int whence;
switch (dir) {
case std::ios::beg:
whence = SEEK_SET;
break;
case std::ios::cur:
default:
whence = SEEK_CUR;
break;
case std::ios::end:
whence = SEEK_END;
break;
}
bool isOK = lseek(hdl_, pos, whence) >= 0;
#endif
if (isOK) return;
throw cybozu::Exception("File:seek") << name_ << cybozu::ErrorNo() << pos << static_cast<int>(dir);
}
uint64_t getSize() const
{
uint64_t fileSize;
#ifdef _WIN32
LARGE_INTEGER size;
bool isOK = GetFileSizeEx(hdl_, &size) != 0;
fileSize = size.QuadPart;
#else
struct stat stat;
bool isOK = fstat(hdl_, &stat) == 0;
fileSize = stat.st_size;
#endif
if (isOK) return fileSize;
throw cybozu::Exception("File:getSize") << name_ << cybozu::ErrorNo();
}
};
/*
name has extension
*/
inline bool HasExtension(const std::string& name, const std::string& extension)
{
const size_t extensionSize = extension.size();
if (extensionSize == 0) return true;
const size_t nameSize = name.size();
if (nameSize < extensionSize + 1) return false;
const char *p = &name[nameSize - extensionSize - 1];
return *p == '.' && memcmp(p + 1, &extension[0], extensionSize) == 0;
}
/*
split name as basename.suffix
*/
inline std::string GetBaseName(const std::string& name, std::string *suffix = 0)
{
size_t pos = name.find_last_of('.');
if (pos == std::string::npos) {
if (suffix) suffix->clear();
return name;
}
if (suffix) {
*suffix = name.substr(pos + 1);
}
return name.substr(0, pos);
}
/**
replace \ with /
*/
inline void ReplaceBackSlash(std::string& str)
{
for (size_t i = 0, n = str.size(); i < n; i++) {
if (str[i] == '\\') str[i] = '/';
}
}
/**
get exe path and baseNamme
@note file name is the form "xxx.exe" then baseName = xxx
*/
inline std::string GetExePath(std::string *baseName = 0)
{
std::string path;
path.resize(4096);
#ifdef _WIN32
if (!GetModuleFileNameA(NULL, &path[0], static_cast<int>(path.size()) - 2)) {
return "";
}
PathRemoveExtensionA(&path[0]);
if (baseName) {
*baseName = PathFindFileNameA(&path[0]);
}
if (::PathRemoveFileSpecA(&path[0])) {
::PathAddBackslashA(&path[0]);
path[0] = static_cast<char>(tolower(path[0]));
path.resize(strlen(&path[0]));
ReplaceBackSlash(path);
}
#else
#if defined(__APPLE__)
uint32_t size = (uint32_t)path.size();
if (_NSGetExecutablePath(&path[0], &size) != 0) {
return "";
}
path.resize(strlen(&path[0]));
#else
int ret = readlink("/proc/self/exe", &path[0], path.size() - 2);
if (ret < 0) return "";
path.resize(ret);
#endif
size_t pos = path.find_last_of('/');
if (pos != std::string::npos) {
if (baseName) {
const std::string name = path.substr(pos + 1);
std::string suffix;
std::string base = GetBaseName(name, &suffix);
if (suffix == "exe") {
*baseName = base;
} else {
*baseName = name;
}
}
path.resize(pos + 1);
}
#endif
return path;
}
/**
get file size
*/
inline uint64_t GetFileSize(const std::string& name)
{
#ifdef _WIN32
struct __stat64 buf;
bool isOK = _stat64(name.c_str(), &buf) == 0;
#else
struct stat buf;
bool isOK = stat(name.c_str(), &buf) == 0;
#endif
if (isOK) return buf.st_size;
throw cybozu::Exception("GetFileSize") << name << cybozu::ErrorNo();
}
/**
verify whether path exists or not
*/
inline bool DoesFileExist(const std::string& path)
{
if (path.empty()) return false;
std::string p = path;
char c = p[p.size() - 1];
if (c == '/' || c == '\\') {
p.resize(p.size() - 1);
}
#ifdef _WIN32
struct _stat buf;
return _stat(p.c_str(), &buf) == 0;
#else
struct stat buf;
return stat(p.c_str(), &buf) == 0;
#endif
}
inline void RenameFile(const std::string& from, const std::string& to)
{
if (DoesFileExist(to)) {
throw cybozu::Exception("RenameFile:file already exist") << from << to;
}
#ifdef _WIN32
bool isOK = ::MoveFileExA(from.c_str(), to.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH) != 0;
#else
bool isOK = ::rename(from.c_str(), to.c_str()) == 0;
#endif
if (!isOK) {
throw cybozu::Exception("RenameFile") << from << to << cybozu::ErrorNo();
}
}
/**
remove file
*/
inline void RemoveFile(const std::string& name)
{
#ifdef _WIN32
bool isOK = DeleteFileA(name.c_str()) != 0;
#else
bool isOK = unlink(name.c_str()) == 0;
#endif
if (!isOK) {
throw cybozu::Exception("RemoveFile") << name << cybozu::ErrorNo();
}
}
/*
remark of isFile()
not directory on Windows
not contain symbolic link on Linux
*/
struct FileInfo {
std::string name;
uint32_t attr; // dwFileAttributes for Windows, d_type for Linux
#ifdef _WIN32
bool isUnknown() const { return attr == 0; }
bool isDirectory() const { verify(); return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; }
bool isFile() const { verify(); return !isDirectory(); }
#else
bool isUnknown() const { return attr == DT_UNKNOWN; }
bool isDirectory() const { verify(); return attr == DT_DIR; }
bool isFile() const { verify(); return attr == DT_REG; }
#endif
FileInfo() : attr(0) {}
FileInfo(const std::string& name, uint32_t attr) : name(name), attr(attr) {}
void verify() const
{
if (isUnknown()) throw cybozu::Exception("FileInfo:unknown attr") << name;
}
};
typedef std::vector<FileInfo> FileList;
namespace file_local {
inline void filterAndPush(FileList& list, const FileInfo& fi, const std::string& extension, bool cond(const std::string&, const std::string&))
{
if (fi.name == "." || fi.name == "..") {
return;
}
if (cond(fi.name, extension)) {
list.push_back(fi);
}
}
} // cybozu::file_local
/**
get file name in dir
@param list [out] FileList
@param dir [in] directory
@param extension [in] select files(including directory) having extension such as "cpp" ; select all if suffix is empty
@param cond [in] filter function (select if cond(targetFile, suffix) is true)
@note "." and ".." are excluded
*/
inline bool GetFileList(FileList &list, const std::string& dir, const std::string& extension = "", bool (*cond)(const std::string&, const std::string&) = cybozu::HasExtension)
{
#ifdef _WIN32
std::string path = dir + "/*";
WIN32_FIND_DATAA fd;
struct Handle {
Handle(HANDLE hdl)
: hdl_(hdl)
{
}
~Handle()
{
if (hdl_ != INVALID_HANDLE_VALUE) {
FindClose(hdl_);
}
}
HANDLE hdl_;
};
Handle hdl(FindFirstFileA(path.c_str(), &fd));
if (hdl.hdl_ == INVALID_HANDLE_VALUE) {
return false;
}
do {
FileInfo fi(fd.cFileName, fd.dwFileAttributes);
file_local::filterAndPush(list, fi, extension, cond);
} while (FindNextFileA(hdl.hdl_, &fd) != 0);
return true;
#else
struct Handle {
DIR *dir_;
Handle(DIR *dir)
: dir_(dir)
{
if (dir_ == 0) {
perror("opendir");
}
}
~Handle()
{
if (dir_) {
if (::closedir(dir_)) {
perror("closedir");
}
}
}
bool isValid() const { return dir_ != 0; }
};
Handle hdl(::opendir(dir.c_str()));
if (!hdl.isValid()) return false;
for (;;) {
struct dirent *dp = ::readdir(hdl.dir_);
if (dp == 0) return true;
FileInfo fi(dp->d_name, (uint8_t)dp->d_type);
file_local::filterAndPush(list, fi, extension, cond);
}
#endif
}
inline FileList GetFileList(const std::string& dir, const std::string& extension = "", bool (*cond)(const std::string&, const std::string&) = cybozu::HasExtension)
{
FileList fl;
if (GetFileList(fl, dir, extension, cond)) return fl;
throw cybozu::Exception("cybozu:GetFileList") << dir << cybozu::ErrorNo();
}
} // cybozu

@ -54,7 +54,7 @@ namespace std { CYBOZU_NAMESPACE_TR1_BEGIN
#pragma warning(push)
#pragma warning(disable : 4099) // missmatch class and struct
#endif
#ifndef __APPLE__
#if !(defined(__APPLE__) && defined(__clang__))
template<class T>
struct hash;
#endif

@ -72,6 +72,9 @@
#endif
#endif
// LLONG_MIN in limits.h is not defined in some env.
#define CYBOZU_LLONG_MIN (-9223372036854775807ll-1)
#define CYBOZU_CPP_VERSION_CPP03 0
#define CYBOZU_CPP_VERSION_TR1 1
#define CYBOZU_CPP_VERSION_CPP11 2
@ -88,13 +91,13 @@
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP17
#elif (__cplusplus >= 201402)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP14
#elif (__cplusplus >= 201103) || (_MSC_VER >= 1500) || defined(__GXX_EXPERIMENTAL_CXX0X__)
#elif (__cplusplus >= 201103) || (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__GXX_EXPERIMENTAL_CXX0X__)
#if defined(_MSC_VER) && (_MSC_VER <= 1600)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1
#else
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP11
#endif
#elif CYBOZU_GNUC_PREREQ(4, 5) || (CYBOZU_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || (__clang_major__ >= 3)
#elif CYBOZU_GNUC_PREREQ(4, 5) || (CYBOZU_GNUC_PREREQ(4, 2) && (defined(__GLIBCXX__) &&__GLIBCXX__ >= 20070719)) || defined(__INTEL_COMPILER) || (__clang_major__ >= 3)
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1
#else
#define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP03
@ -115,7 +118,7 @@
#endif
#ifndef CYBOZU_OS_BIT
#if defined(_WIN64) || defined(__x86_64__) || defined(__AARCH64EL__) || defined(__EMSCRIPTEN__)
#if defined(_WIN64) || defined(__x86_64__) || defined(__AARCH64EL__) || defined(__EMSCRIPTEN__) || defined(__LP64__)
#define CYBOZU_OS_BIT 64
#else
#define CYBOZU_OS_BIT 32
@ -143,6 +146,8 @@
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE
#elif (CYBOZU_HOST == CYBOZU_HOST_ARM) && (defined(__ARM_EABI__) || defined(__AARCH64EL__))
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE
#elif defined(__s390x__)
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_BIG
#else
#define CYBOZU_ENDIAN CYBOZU_ENDIAN_UNKNOWN
#endif
@ -150,8 +155,10 @@
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
#define CYBOZU_NOEXCEPT noexcept
#define CYBOZU_NULLPTR nullptr
#else
#define CYBOZU_NOEXCEPT throw()
#define CYBOZU_NULLPTR 0
#endif
namespace cybozu {
template<class T>

@ -5,7 +5,6 @@
@author MITSUNARI Shigeo(@herumi)
*/
#include <limits.h>
#ifndef CYBOZU_DONT_USE_STRING
#include <string>
#endif
@ -122,7 +121,7 @@ size_t uintToBin(char *buf, size_t bufSize, UT x)
template<class T>
size_t intToDec(char *buf, size_t bufSize, T x)
{
if (x == LLONG_MIN) {
if (x == CYBOZU_LLONG_MIN) {
const char minStr[] = "-9223372036854775808";
const size_t minStrLen = sizeof(minStr) - 1;
if (bufSize < minStrLen) {

@ -8,6 +8,9 @@
*/
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <pthread.h>

@ -145,7 +145,7 @@ bool convertInt(T* x, const char *str)
if (factor > 1) {
if ((std::numeric_limits<T>::min)() / factor <= y
&& y <= (std::numeric_limits<T>::max)() / factor) {
*x = y * factor;
*x = static_cast<T>(y * factor);
} else {
return false;
}
@ -155,9 +155,29 @@ bool convertInt(T* x, const char *str)
return true;
}
template<class T>
void convertToStr(std::ostream& os, const T* p)
{
os << *p;
}
template<>inline void convertToStr(std::ostream& os, const int8_t* p)
{
os << static_cast<int>(*p);
}
template<>inline void convertToStr(std::ostream& os, const uint8_t* p)
{
os << static_cast<int>(*p);
}
#define CYBOZU_OPTION_DEFINE_CONVERT_INT(type) \
template<>inline bool convert(type* x, const char *str) { return convertInt(x, str); }
CYBOZU_OPTION_DEFINE_CONVERT_INT(int8_t)
CYBOZU_OPTION_DEFINE_CONVERT_INT(uint8_t)
CYBOZU_OPTION_DEFINE_CONVERT_INT(int16_t)
CYBOZU_OPTION_DEFINE_CONVERT_INT(uint16_t)
CYBOZU_OPTION_DEFINE_CONVERT_INT(int)
CYBOZU_OPTION_DEFINE_CONVERT_INT(long)
CYBOZU_OPTION_DEFINE_CONVERT_INT(long long)
@ -185,7 +205,7 @@ struct Holder : public HolderBase {
std::string toStr() const
{
std::ostringstream os;
os << *p_;
convertToStr(os, p_);
return os.str();
}
const void *get() const { return (void*)p_; }
@ -345,7 +365,7 @@ class Option {
template<class T, class U>
void append(T *pvar, const U& defaultVal, bool isMust, const char *opt, const std::string& help = "")
{
*pvar = defaultVal;
*pvar = static_cast<const T&>(defaultVal);
appendSub(pvar, N_is1, isMust, opt, help);
}
/*

@ -11,13 +11,14 @@
#include <cybozu/exception.hpp>
#endif
#ifdef _WIN32
#include <winsock2.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <wincrypt.h>
#ifdef _MSC_VER
#pragma comment (lib, "advapi32.lib")
#endif
#include <cybozu/critical_section.hpp>
#else
#include <sys/types.h>
#include <fcntl.h>
@ -32,10 +33,9 @@ public:
#ifdef _WIN32
RandomGenerator()
: prov_(0)
, pos_(bufSize)
{
DWORD flagTbl[] = { 0, CRYPT_NEWKEYSET };
for (int i = 0; i < 2; i++) {
DWORD flagTbl[] = { CRYPT_VERIFYCONTEXT | CRYPT_SILENT, 0, CRYPT_MACHINE_KEYSET };
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(flagTbl); i++) {
if (CryptAcquireContext(&prov_, NULL, NULL, PROV_RSA_FULL, flagTbl[i]) != 0) return;
}
#ifdef CYBOZU_DONT_USE_EXCEPTION
@ -62,29 +62,11 @@ public:
template<class T>
void read(bool *pb, T *buf, size_t bufNum)
{
cybozu::AutoLockCs al(cs_);
const size_t byteSize = sizeof(T) * bufNum;
if (byteSize > bufSize) {
if (!read_inner(buf, byteSize)) {
*pb = false;
return;
}
} else {
if (pos_ + byteSize > bufSize) {
read_inner(buf_, bufSize);
pos_ = 0;
}
memcpy(buf, buf_ + pos_, byteSize);
pos_ += byteSize;
}
*pb = true;
*pb = read_inner(buf, byteSize);
}
private:
HCRYPTPROV prov_;
static const size_t bufSize = 1024;
char buf_[bufSize];
size_t pos_;
cybozu::CriticalSection cs_;
#else
RandomGenerator()
: fp_(::fopen("/dev/urandom", "rb"))

@ -13,6 +13,7 @@
#ifndef CYBOZU_DONT_USE_STRING
#include <string>
#endif
#include <memory.h>
#ifdef CYBOZU_USE_OPENSSL_SHA
#ifdef __APPLE__
@ -468,3 +469,61 @@ public:
} // cybozu
#endif
namespace cybozu {
namespace sha2_local {
inline void hmac256_inner(void *hmac, const void *key, size_t keySize, const void *msg, size_t msgSize, bool addZeroByte)
{
const uint8_t ipad = 0x36;
const uint8_t opad = 0x5c;
uint8_t k[64];
Sha256 hash;
if (keySize > 64) {
hash.digest(k, 32, key, keySize);
hash.clear();
keySize = 32;
} else {
memcpy(k, key, keySize);
}
for (size_t i = 0; i < keySize; i++) {
k[i] = k[i] ^ ipad;
}
memset(k + keySize, ipad, 64 - keySize);
hash.update(k, 64);
if (addZeroByte) {
hash.update(msg, msgSize);
const char zero = '\x00';
hash.digest(hmac, 32, &zero, 1);
} else {
hash.digest(hmac, 32, msg, msgSize);
}
hash.clear();
for (size_t i = 0; i < 64; i++) {
k[i] = k[i] ^ (ipad ^ opad);
}
hash.update(k, 64);
hash.digest(hmac, 32, hmac, 32);
}
} // cybozu::sha2_local
/*
HMAC-SHA-256
hmac must have 32 bytes buffer
*/
inline void hmac256(void *hmac, const void *key, size_t keySize, const void *msg, size_t msgSize)
{
sha2_local::hmac256_inner(hmac, key, keySize, msg, msgSize, false);
}
/*
hmac256 for [msg] + [\x00]
*/
inline void hmac256addZeroByte(void *hmac, const void *key, size_t keySize, const void *msg, size_t msgSize)
{
sha2_local::hmac256_inner(hmac, key, keySize, msg, msgSize, true);
}
} // cybozu

@ -0,0 +1,785 @@
#pragma once
/**
@file
@brief tiny socket class
@author MITSUNARI Shigeo(@herumi)
@author MITSUNARI Shigeo
@remark mingw requires -lws2_32 option
*/
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h> // for socklen_t
#ifdef _MSC_VER
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")
#pragma warning(push)
#pragma warning(disable : 4127) // constant condition
#endif
#else
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <memory.h>
#include <signal.h>
#endif
#ifndef NDEBUG
#include <stdio.h>
#endif
#include <cybozu/atomic.hpp>
#include <cybozu/exception.hpp>
#include <cybozu/itoa.hpp>
#include <string>
#ifdef __linux__
// #define CYBOZU_SOCKET_USE_EPOLL
#include <sys/epoll.h>
#endif
namespace cybozu {
#ifdef _MSC_VER
struct NetErrorNo : public cybozu::ErrorNo {
NetErrorNo(NativeErrorNo err)
: cybozu::ErrorNo(err)
{
}
NetErrorNo()
: cybozu::ErrorNo(WSAGetLastError())
{
}
};
#else
typedef cybozu::ErrorNo NetErrorNo;
#endif
#ifdef CYBOZU_SOCKET_USE_EPOLL
namespace experimental {
struct EpollEvent {
struct epoll_event ev_;
EpollEvent()
{
memset(&ev_, 0, sizeof(ev_));
}
void set(int fd, uint32_t events = EPOLLIN)
{
ev_.events = events;
ev_.data.fd = fd;
}
int getFd() const { return ev_.data.fd; }
};
class Epoll {
int efd_;
bool verify(const char *msg, int ret, int *err) const {
if (ret >= 0) return true;
if (err == 0) throw cybozu::Exception(msg) << cybozu::NetErrorNo();
*err = errno;
return false;
}
public:
Epoll() : efd_(-1) {}
bool init(int *err = 0)
{
efd_ = ::epoll_create1(0);
return verify("Epoll:init", efd_, err);
}
~Epoll()
{
if (efd_ >= 0) ::close(efd_);
}
/*
throw if err == NULL
*/
bool ctrl(int op, int fd, EpollEvent *ev, int *err = 0) {
int ret = ::epoll_ctl(efd_, op, fd, &ev->ev_);
return verify("Epoll:ctrl", ret, err);
}
bool add(int fd, uint32_t events = EPOLLIN, int *err = 0) {
EpollEvent ev;
ev.set(fd, events);
return ctrl(EPOLL_CTL_ADD, fd, &ev, err);
}
bool del(int fd, int *err = 0) {
return ctrl(EPOLL_CTL_DEL, fd, NULL, err);
}
/*
msec : 0 : block
*/
int wait(EpollEvent *ev, int maxEv, int msec = 0)
{
/*
0 : return immediately
-1 : block indefinitely
*/
if (msec == 0) {
msec = -1;
} else if (msec == -1) {
msec = 0;
}
int ret = ::epoll_wait(efd_, &ev->ev_, maxEv, msec);
if (ret == 0) return 0; // timeout
if (ret < 0) return -errno;
return ret;
}
};
struct AutoLock {
Epoll& ep_;
int fd_;
AutoLock(Epoll& ep, int fd, int events = EPOLLIN)
: ep_(ep)
, fd_(fd)
{
ep_.add(fd, events);
}
~AutoLock()
{
int err;
ep_.del(fd_, &err);
}
};
} // cybozu::experimental
#endif
namespace ssl {
class ClientSocket;
};
namespace socket_local {
#ifdef _WIN32
typedef SOCKET SocketHandle;
#else
typedef int SocketHandle;
#endif
struct InitTerm {
/** call once for init */
InitTerm()
{
#ifdef _WIN32
WSADATA data;
int err = ::WSAStartup(MAKEWORD(2, 2), &data);
if (err) {
fprintf(stderr, "WSAStartup failed : %d\n", err);
exit(1);
}
#else
::signal(SIGPIPE, SIG_IGN);
#endif
}
/** call once for term */
~InitTerm()
{
#ifdef _WIN32
::WSACleanup();
#endif
}
void dummyCall() { }
};
template<int dummy = 0>
struct InstanceIsHere { static InitTerm it_; };
template<int dummy>
InitTerm InstanceIsHere<dummy>::it_;
struct DummyCall {
DummyCall() { InstanceIsHere<>::it_.dummyCall(); }
};
} // cybozu::socket_local
class SocketAddr {
union {
// http://www.coins.tsukuba.ac.jp/~syspro/2010/No6_files/sockaddr.html
struct sockaddr sa; /* 16byte */
struct sockaddr_in v4; /* 16byte */
struct sockaddr_in6 v6;
} addr_;
socklen_t addrlen_;
int family_;
friend class Socket;
void verify() // call in only Socket::accept
{
if (addrlen_ == sizeof(addr_.v4) && addr_.sa.sa_family == AF_INET) {
family_ = AF_INET;
return;
}
if (addrlen_ == sizeof(addr_.v6) && addr_.sa.sa_family == AF_INET6) {
family_ = AF_INET6;
return;
}
throw cybozu::Exception("cybozu:SocketAddr:verify") << addrlen_;
}
public:
SocketAddr()
: addrlen_(0)
, family_(0)
{
}
SocketAddr(const std::string& address, uint16_t port, bool forceIpV6 = false)
{
set(address, port, forceIpV6);
}
void set(const std::string& address, uint16_t port, bool forceIpV6 = false)
{
char portStr[16];
CYBOZU_SNPRINTF(portStr, sizeof(portStr), "%d", port);
memset(&addr_, 0, sizeof(addr_));
addrlen_ = 0;
family_ = 0;
struct addrinfo *result = 0;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_NUMERICSERV; // AI_PASSIVE;
const int s = getaddrinfo(address.c_str(), portStr, &hints, &result);
// s == EAI_AGAIN
if (s || forceIpV6) {
hints.ai_family = AF_INET6;
hints.ai_flags |= AI_V4MAPPED;
if (getaddrinfo(address.c_str(), portStr, &hints, &result)) {
goto ERR_EXIT;
}
}
{
bool found = false;
for (const struct addrinfo *p = result; p; p = p->ai_next) {
const int family = p->ai_family;
if (family == hints.ai_family) {
if (p->ai_addrlen > sizeof(addr_)) {
break;
}
memcpy(&addr_, p->ai_addr, p->ai_addrlen);
addrlen_ = (socklen_t)p->ai_addrlen;
family_ = family;
found = true;
break;
}
}
freeaddrinfo(result);
if (found) return;
}
ERR_EXIT:
throw cybozu::Exception("SocketAddr:set") << address << port << cybozu::NetErrorNo();
}
socklen_t getSize() const { return addrlen_; }
int getFamily() const { return family_; }
const struct sockaddr *get() const { return &addr_.sa; }
uint16_t getPort() const {
if (family_ == AF_INET) {
return ntohs(addr_.v4.sin_port);
} else if (family_ == AF_INET6) {
return ntohs(addr_.v6.sin6_port);
}
throw cybozu::Exception("SocketAddr:getPort:bad family") << family_;
}
// compare addr without port
bool hasSameAddr(const SocketAddr& rhs) const
{
const uint8_t *v4 = 0;
const uint8_t *v6 = 0;
if (family_ == AF_INET) {
if (rhs.family_ == AF_INET) return memcmp(&addr_.v4.sin_addr, &rhs.addr_.v4.sin_addr, sizeof(in_addr)) == 0;
if (rhs.family_ != AF_INET6) return false;
v4 = (const uint8_t*)&addr_.v4.sin_addr;
v6 = (const uint8_t*)&rhs.addr_.v6.sin6_addr;
} else if (family_ != AF_INET6) {
return false;
} else {
if (rhs.family_ == AF_INET6) return memcmp(&addr_.v6.sin6_addr, &rhs.addr_.v6.sin6_addr, sizeof(in6_addr)) == 0;
if (rhs.family_ != AF_INET) return false;
v4 = (const uint8_t*)&rhs.addr_.v4.sin_addr;
v6 = (const uint8_t*)&addr_.v6.sin6_addr;
}
// Ipv6-mapped?
const uint8_t header[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
return memcmp(v6, header, 12) == 0 && memcmp(v6 + 12, v4, 4) == 0;
}
std::string toStr() const
{
if (family_ == AF_INET || family_ == AF_INET6) {
char buf[INET6_ADDRSTRLEN];
assert(INET_ADDRSTRLEN <= INET6_ADDRSTRLEN);
const bool isIPv4 = family_ == AF_INET;
const void *pa = isIPv4 ? (const void*)&addr_.v4.sin_addr : (const void*)&addr_.v6.sin6_addr;
// not "const void*" because of vc
const char *p = inet_ntop(family_, const_cast<void*>(pa), buf, sizeof(buf));
if (!p) throw cybozu::Exception("cybozu:SocketAddr:toStr") << cybozu::NetErrorNo();
if (isIPv4) return std::string(p) + ':' + cybozu::itoa(getPort());
return std::string("[") + p + "]:" + cybozu::itoa(getPort());
}
throw cybozu::Exception("cybozu:SocketAddr:toStr:bad family_") << family_;
}
};
/*
socket class
@note ower is moved if copied
*/
class Socket {
friend class cybozu::ssl::ClientSocket;
private:
cybozu::socket_local::SocketHandle sd_;
Socket(const Socket&);
void operator=(const Socket&);
#ifdef WIN32
void setTimeout(int type, int msec)
{
setSocketOption(type, msec);
}
/* return msec */
int getTimeout(int type) const
{
return getSocketOption(type);
}
#else
void setTimeout(int type, int msec)
{
struct timeval t;
t.tv_sec = msec / 1000;
t.tv_usec = (msec % 1000) * 1000;
setSocketOption(type, t);
}
/* return msec */
int getTimeout(int type) const
{
struct timeval t;
getSocketOption(type, &t);
return t.tv_sec * 1000 + t.tv_usec / 1000; /* msec */
}
#endif
void setBlocking(bool isBlocking)
{
#ifdef _WIN32
u_long val = isBlocking ? 0 : 1;
int ret = ::ioctlsocket(sd_, FIONBIO, &val);
#else
int val = isBlocking ? 0 : 1;
int ret = ::ioctl(sd_, FIONBIO, &val);
#endif
if (ret < 0) throw cybozu::Exception("Socket:setBlocking") << cybozu::NetErrorNo() << isBlocking;
}
public:
#ifndef _WIN32
static const int INVALID_SOCKET = -1;
#endif
Socket()
: sd_(INVALID_SOCKET)
{
}
bool isValid() const { return sd_ != INVALID_SOCKET; }
// move
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
Socket(Socket&& rhs)
: sd_(INVALID_SOCKET)
{
sd_ = cybozu::AtomicExchange(&rhs.sd_, sd_);
}
#endif
// close and move
void moveFrom(Socket& rhs)
{
close();
sd_ = cybozu::AtomicExchange(&rhs.sd_, INVALID_SOCKET);
}
#if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
void operator=(Socket&& rhs)
#else
void operator=(Socket& rhs)
#endif
{
moveFrom(rhs);
}
~Socket()
{
close(cybozu::DontThrow);
}
bool close(bool dontThrow = false)
{
cybozu::socket_local::SocketHandle sd = cybozu::AtomicExchange(&sd_, INVALID_SOCKET);
if (sd == INVALID_SOCKET) return true;
#ifdef _WIN32
// ::shutdown(sd, SD_SEND);
// shutdown is called in closesocket
bool isOK = ::closesocket(sd) == 0;
#else
bool isOK = ::close(sd) == 0;
#endif
if (!dontThrow && !isOK) throw cybozu::Exception("Socket:close") << cybozu::NetErrorNo();
return isOK;
}
/*
how 0 : SHUTRD ; disallow read
1 : SHUT_WR ; disallow write
2 : SHUT_RDWR ; disallow read/write
*/
bool shutdown(int how, bool dontThrow = false)
{
bool isOK = ::shutdown(sd_, how) == 0;
if (!dontThrow && !isOK) throw cybozu::Exception("Socket:waitForClose:shutdown") << cybozu::NetErrorNo();
return isOK;
}
/*
send FIN and wait for remote's close().
this function is used for the following situation.
sock.write()
sock.waitForClose()
sock.close()
*/
void waitForClose()
{
if (sd_ == INVALID_SOCKET) return;
// send FIN and this socket can't write any data.
shutdown(1);
// wait for FIN from the peer.
char buf[1];
ssize_t readSize = readSome(buf, sizeof(buf));
if (readSize != 0) {
throw cybozu::Exception("Socket:waitForClose:readSome:bad size") << readSize;
}
}
/*!
receive data
@param buf [out] receive buffer
@param bufSize [in] receive buffer size(byte)
@note return read size
*/
size_t readSome(void *buf, size_t bufSize)
{
int size = (int)(std::min)((size_t)0x7fffffff, bufSize);
#ifdef _WIN32
int readSize = ::recv(sd_, (char *)buf, size, 0);
#else
RETRY:
ssize_t readSize = ::read(sd_, buf, size);
if (readSize < 0 && errno == EINTR) goto RETRY;
#endif
if (readSize < 0) throw cybozu::Exception("Socket:readSome") << cybozu::NetErrorNo() << bufSize;
return readSize;
}
/*!
receive all data unless timeout
@param buf [out] receive buffer
@param bufSize [in] receive buffer size(byte)
*/
void read(void *buf, size_t bufSize)
{
char *p = (char *)buf;
while (bufSize > 0) {
size_t readSize = readSome(p, bufSize);
if (readSize == 0) throw cybozu::Exception("Socket:read:readSize is zero");
p += readSize;
bufSize -= readSize;
}
}
/*!
write all data
@param buf [out] send buffer
@param bufSize [in] send buffer size(byte)
*/
void write(bool *pb, const void *buf, size_t bufSize)
{
const char *p = (const char *)buf;
while (bufSize > 0) {
int size = (int)(std::min)(size_t(0x7fffffff), bufSize);
#ifdef _WIN32
int writeSize = ::send(sd_, p, size, 0);
#else
int writeSize = ::write(sd_, p, size);
if (writeSize < 0 && errno == EINTR) continue;
#endif
if (writeSize < 0) {
*pb = false;
return;
}
p += writeSize;
bufSize -= writeSize;
}
*pb = true;
}
void write(const void *buf, size_t bufSize)
{
bool b;
write(&b, buf, bufSize);
if (!b) throw cybozu::Exception("Socket:write") << cybozu::NetErrorNo() << bufSize;
}
/**
connect to address:port
@param address [in] address
@param port [in] port
@param msec: 0 : block
*/
void connect(const std::string& address, uint16_t port, int msec = 0)
{
SocketAddr addr;
addr.set(address, port);
connect(addr, msec);
}
/**
connect to resolved socket addr
*/
void connect(const cybozu::SocketAddr& addr, int msec = 0)
{
if (isValid()) throw cybozu::Exception("Socket:connect:already connect");
sd_ = ::socket(addr.getFamily(), SOCK_STREAM, IPPROTO_TCP);
if (!isValid()) {
throw cybozu::Exception("Socket:connect:socket") << cybozu::NetErrorNo();
}
if (msec == 0) {
if (::connect(sd_, addr.get(), addr.getSize()) < 0) {
throw cybozu::Exception("Socket:connect") << cybozu::NetErrorNo() << addr.toStr();
}
} else {
setBlocking(false);
if (::connect(sd_, addr.get(), addr.getSize()) < 0) {
#ifdef _WIN32
bool inProgress = WSAGetLastError() == WSAEWOULDBLOCK;
#else
bool inProgress = errno == EINPROGRESS;
#endif
if (!inProgress) throw cybozu::Exception("Socket:connect:not in progress") << cybozu::NetErrorNo() << addr.toStr();
if (!queryAccept(msec, false)) throw cybozu::Exception("Socket:connect:timeout") << addr.toStr();
int err = getSocketOption(SO_ERROR);
if (err != 0) throw cybozu::Exception("Socket::connect:bad socket") << cybozu::NetErrorNo(err);
}
setBlocking(true);
}
}
static const int allowIPv4 = 1;
static const int allowIPv6 = 2;
/**
init for server
@param port [in] port number
*/
void bind(uint16_t port, int mode = allowIPv4 | allowIPv6)
{
const int family = (mode & allowIPv6) ? AF_INET6 : AF_INET;
sd_ = ::socket(family, SOCK_STREAM, IPPROTO_TCP);
if (!isValid()) {
throw cybozu::Exception("Socket:bind:socket") << cybozu::NetErrorNo();
}
setSocketOption(SO_REUSEADDR, 1);
struct sockaddr_in6 addr6;
struct sockaddr_in addr4;
struct sockaddr *addr;
socklen_t addrLen;
if (mode & allowIPv6) {
setSocketOption(IPV6_V6ONLY, (mode & allowIPv4) ? 0 : 1, IPPROTO_IPV6);
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = htons(port);
addr = (struct sockaddr*)&addr6;
addrLen = sizeof(addr6);
} else {
memset(&addr4, 0, sizeof(addr4));
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port);
addr = (struct sockaddr*)&addr4;
addrLen = sizeof(addr4);
}
if (::bind(sd_, addr, addrLen) == 0) {
if (::listen(sd_, SOMAXCONN) == 0) {
return;
}
}
cybozu::NetErrorNo keep;
close(cybozu::DontThrow);
throw cybozu::Exception("Socket:bind") << keep;
}
/**
return positive if accepted
return zero if timeout
return negative(-errno) if error
*/
int queryAcceptNoThrow(int msec = 1000, bool checkWrite = true)
{
if (sd_ == INVALID_SOCKET) return -EBADF;
#ifdef CYBOZU_SOCKET_USE_EPOLL
int err;
experimental::Epoll ep;
if (!ep.init(&err)) return -err;
uint32_t events = checkWrite ? EPOLLIN : EPOLLOUT;
experimental::AutoLock al(ep, sd_, events);
experimental::EpollEvent ev;
int ret = ep.wait(&ev, 1, msec);
if (ret != 1) return ret;
assert(ev.getFd() == sd_);
return ret;
#else
#ifndef _WIN32
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms739169.aspx
if (sd_ >= FD_SETSIZE) return -EMFILE;
#endif
struct timeval timeout;
timeout.tv_sec = msec / 1000;
timeout.tv_usec = (msec % 1000) * 1000;
fd_set fds;
FD_ZERO(&fds);
FD_SET((unsigned)sd_, &fds);
int fdNum;
if (checkWrite) {
fdNum = ::select((int)sd_ + 1, &fds, 0, 0, &timeout);
} else {
fdNum = ::select((int)sd_ + 1, 0, &fds, 0, &timeout);
}
if (fdNum < 0) return -errno;
return fdNum;
#endif
}
/**
return true if acceptable, otherwise false
return false if one second passed
while (!server.queryAccept()) {
}
client.accept(server);
*/
bool queryAccept(int msec = 1000, bool checkWrite = true)
{
int ret = queryAcceptNoThrow(msec, checkWrite);
if (ret < 0) throw cybozu::Exception("Socket:queryAccept") << cybozu::NetErrorNo(-ret);
return ret > 0;
}
/**
accept for server
*/
void accept(Socket& client, SocketAddr *paddr = 0) const
{
if (paddr) {
struct sockaddr *psa = &paddr->addr_.sa;
paddr->addrlen_ = sizeof(paddr->addr_);
client.sd_ = ::accept(sd_, psa, &paddr->addrlen_);
paddr->verify();
} else {
client.sd_ = ::accept(sd_, 0, 0);
}
if (!client.isValid()) throw cybozu::Exception("Socket:accept") << cybozu::NetErrorNo();
}
template<typename T>
void setSocketOption(int optname, const T& value, int level = SOL_SOCKET)
{
bool isOK = setsockopt(sd_, level, optname, cybozu::cast<const char*>(&value), sizeof(T)) == 0;
if (!isOK) throw cybozu::Exception("Socket:setSocketOption") << cybozu::NetErrorNo();
}
template<typename T>
void getSocketOption(int optname, T* value, int level = SOL_SOCKET) const
{
socklen_t len = (socklen_t)sizeof(T);
bool isOK = getsockopt(sd_, level, optname, cybozu::cast<char*>(value), &len) == 0;
if (!isOK) throw cybozu::Exception("Socket:getSocketOption") << cybozu::NetErrorNo();
}
int getSocketOption(int optname) const
{
int ret;
getSocketOption(optname, &ret);
return ret;
}
/**
setup linger
*/
void setLinger(uint16_t l_onoff, uint16_t l_linger)
{
struct linger linger;
linger.l_onoff = l_onoff;
linger.l_linger = l_linger;
setSocketOption(SO_LINGER, &linger);
}
/**
get receive buffer size
@retval positive buffer size(byte)
@retval -1 error
*/
int getReceiveBufferSize() const
{
return getSocketOption(SO_RCVBUF);
}
/**
set receive buffer size
@param size [in] buffer size(byte)
*/
void setReceiveBufferSize(int size)
{
setSocketOption(SO_RCVBUF, size);
}
/**
get send buffer size
@retval positive buffer size(byte)
@retval -1 error
*/
int getSendBufferSize() const
{
return getSocketOption(SO_SNDBUF);
}
/**
sed send buffer size
@param size [in] buffer size(byte)
*/
void setSendBufferSize(int size)
{
setSocketOption(SO_SNDBUF, size);
}
/**
set send timeout
@param msec [in] msec
*/
void setSendTimeout(int msec)
{
setTimeout(SO_SNDTIMEO, msec);
}
/**
set receive timeout
@param msec [in] msec
*/
void setReceiveTimeout(int msec)
{
setTimeout(SO_RCVTIMEO, msec);
}
/**
get send timeout(msec)
*/
int getSendTimeout() const
{
return getTimeout(SO_SNDTIMEO);
}
/**
get receive timeout(msec)
*/
int getReceiveTimeout() const
{
return getTimeout(SO_RCVTIMEO);
}
};
} // cybozu
#ifdef _MSC_VER
#pragma warning(pop)
#endif

@ -9,7 +9,9 @@
#include <string>
#include <iosfwd>
#endif
#ifndef CYBOZU_DONT_USE_EXCEPTION
#include <cybozu/exception.hpp>
#endif
#include <memory.h>
namespace cybozu {

@ -0,0 +1,281 @@
#pragma once
/**
@file
@brief tiny time class
@author MITSUNARI Shigeo(@herumi)
*/
#include <ctime>
#include <cybozu/exception.hpp>
#include <cybozu/atoi.hpp>
#include <cybozu/itoa.hpp>
#ifdef _WIN32
#include <sys/timeb.h>
#else
#include <sys/time.h>
#endif
namespace cybozu {
/**
time struct with time_t and msec
@note time MUST be latesr than 1970/1/1
*/
class Time {
static const uint64_t epochBias = 116444736000000000ull;
std::time_t time_;
int msec_;
public:
explicit Time(std::time_t time = 0, int msec = 0)
: time_(time)
, msec_(msec)
{
}
explicit Time(bool doSet)
{
if (doSet) setCurrentTime();
}
Time& setTime(std::time_t time, int msec = 0)
{
time_ = time;
msec_ = msec;
return *this;
}
/*
Windows FILETIME is defined as
struct FILETILME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
};
the value represents the number of 100-nanosecond intervals since January 1, 1601 (UTC).
*/
void setByFILETIME(uint32_t low, uint32_t high)
{
const uint64_t fileTime = (((uint64_t(high) << 32) | low) - epochBias) / 10000;
time_ = fileTime / 1000;
msec_ = fileTime % 1000;
}
/*
DWORD is defined as unsigned long in windows
*/
template<class dword>
void getFILETIME(dword& low, dword& high) const
{
const uint64_t fileTime = (time_ * 1000 + msec_) * 10000 + epochBias;
low = dword(fileTime);
high = dword(fileTime >> 32);
}
explicit Time(const std::string& in)
{
fromString(in);
}
explicit Time(const char *in)
{
fromString(in, in + strlen(in));
}
const std::time_t& getTime() const { return time_; }
int getMsec() const { return msec_; }
double getTimeSec() const { return time_ + msec_ * 1e-3; }
void addSec(int sec) { time_ += sec; }
bool operator<(const Time& rhs) const { return (time_ < rhs.time_) || (time_ == rhs.time_ && msec_ < rhs.msec_); }
// bool operator<=(const Time& rhs) const { return (*this < rhs) || (*this == rhs); }
// bool operator>(const Time& rhs) const { return rhs < *this; }
bool operator==(const Time& rhs) const { return (time_ == rhs.time_) && (msec_ == rhs.msec_); }
bool operator!=(const Time& rhs) const { return !(*this == rhs); }
/**
set time from string such as
2009-Jan-23T02:53:44Z
2009-Jan-23T02:53:44.078Z
2009-01-23T02:53:44Z
2009-01-23T02:53:44.078Z
@note 'T' may be ' '. '-' may be '/'. last char 'Z' is omissible
*/
void fromString(bool *pb, const std::string& in) { fromString(pb, &in[0], &in[0] + in.size()); }
void fromString(const std::string& in) { fromString(0, in); }
void fromString(bool *pb, const char *begin, const char *end)
{
const size_t len = end - begin;
if (len >= 19) {
const char *p = begin;
struct tm tm;
int num;
bool b;
tm.tm_year = getNum(&b, p, 4, 1970, 3000) - 1900;
if (!b) goto ERR;
p += 4;
char sep = *p++;
if (sep != '-' && sep != '/') goto ERR;
p = getMonth(&num, p);
if (p == 0) goto ERR;
tm.tm_mon = num;
if (*p++ != sep) goto ERR;
tm.tm_mday = getNum(&b, p, 2, 1, 31);
if (!b) goto ERR;
p += 2;
if (*p != ' ' && *p != 'T') goto ERR;
p++;
tm.tm_hour = getNum(&b, p, 2, 0, 23);
if (!b) goto ERR;
p += 2;
if (*p++ != ':') goto ERR;
tm.tm_min = getNum(&b, p, 2, 0, 59);
if (!b) goto ERR;
p += 2;
if (*p++ != ':') goto ERR;
tm.tm_sec = getNum(&b, p, 2, 0, 59);
if (!b) goto ERR;
p += 2;
if (p == end) {
msec_ = 0;
} else if (p + 1 == end && *p == 'Z') {
msec_ = 0;
p++;
} else if (*p == '.' && (p + 4 == end || (p + 5 == end && *(p + 4) == 'Z'))) {
msec_ = getNum(&b, p + 1, 3, 0, 999);
if (!b) goto ERR;
// p += 4;
} else {
goto ERR;
}
#ifdef _WIN32
time_ = _mkgmtime64(&tm);
if (time_ == -1) goto ERR;
#else
time_ = timegm(&tm);
#endif
if (pb) {
*pb = true;
}
return;
}
ERR:
if (pb) {
*pb = false;
return;
}
throw cybozu::Exception("time::fromString") << std::string(begin, 24);
}
void fromString(const char *begin, const char *end) { fromString(0, begin, end); }
/**
get current time with format
@param out [out] output string
@param format [in] foramt for strftime and append three digits for msec
@param appendMsec [in] appemd <mmm>
@param doClear (append to out if false)
@note ex. "%Y-%b-%d %H:%M:%S." to get 2009-Jan-23 02:53:44.078
*/
void toString(std::string& out, const char *format, bool appendMsec = true, bool doClear = true) const
{
if (doClear) out.clear();
char buf[128];
struct tm tm;
#ifdef _WIN32
bool isOK = _gmtime64_s(&tm, &time_) == 0;
#else
bool isOK = gmtime_r(&time_, &tm) != 0;
#endif
if (!isOK) throw cybozu::Exception("time::toString") << time_;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
if (std::strftime(buf, sizeof(buf), format, &tm) == 0) {
throw cybozu::Exception("time::toString::too long") << format << time_;
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
out += buf;
if (appendMsec) {
out += cybozu::itoaWithZero(msec_, 3);
}
}
/**
get current time such as 2009-01-23 02:53:44.078
@param out [out] sink string
*/
void toString(std::string& out, bool appendMsec = true, bool doClear = true) const
{
const char *format = appendMsec ? "%Y-%m-%d %H:%M:%S." : "%Y-%m-%d %H:%M:%S";
toString(out, format, appendMsec, doClear);
}
std::string toString(bool appendMsec = true) const { std::string out; toString(out, appendMsec); return out; }
/**
get current time
*/
Time& setCurrentTime()
{
#ifdef _WIN32
struct _timeb timeb;
_ftime_s(&timeb);
time_ = timeb.time;
msec_ = timeb.millitm;
#else
struct timeval tv;
gettimeofday(&tv, 0);
time_ = tv.tv_sec;
msec_ = tv.tv_usec / 1000;
#endif
return *this;
}
private:
int getNum(bool *b, const char *in, size_t len, int min, int max) const
{
int ret = cybozu::atoi(b, in, len);
if (min <= ret && ret <= max) {
return ret;
} else {
*b = false;
return 0;
}
}
/*
convert month-str to [0, 11]
@param ret [out] return idx
@param p [in] month-str
@retval next pointer or null
*/
const char *getMonth(int *ret, const char *p) const
{
static const char monthTbl[12][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(monthTbl); i++) {
if (memcmp(p, monthTbl[i], 3) == 0) {
*ret = (int)i;
return p + 3;
}
}
bool b;
*ret = getNum(&b, p, 2, 1, 12) - 1;
if (b) {
return p + 2;
} else {
return 0;
}
}
};
inline std::ostream& operator<<(std::ostream& os, const cybozu::Time& time)
{
return os << time.toString();
}
inline double GetCurrentTimeSec()
{
return cybozu::Time(true).getTimeSec();
}
} // cybozu

@ -62,16 +62,32 @@ public:
friend class SecretKey;
friend class PublicKey;
public:
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
S_.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
S_.save(pb, os, ioMode);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
S_.load(is, ioMode);
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("Signature:load");
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
S_.save(os, ioMode);
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("Signature:save");
}
#endif
friend std::istream& operator>>(std::istream& is, Signature& self)
{
self.load(is, fp::detectIoMode(G1::getIoMode(), is));
@ -155,16 +171,32 @@ public:
friend class SecretKey;
friend class Signature;
public:
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
xQ_.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
xQ_.save(pb, os, ioMode);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
xQ_.load(is, ioMode);
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("PublicKey:load");
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
xQ_.save(os, ioMode);
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("PublicKey:save");
}
#endif
friend std::istream& operator>>(std::istream& is, PublicKey& self)
{
self.load(is, fp::detectIoMode(G2::getIoMode(), is));
@ -208,16 +240,32 @@ public:
friend class PublicKey;
friend class Signature;
public:
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
x_.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
x_.save(pb, os, ioMode);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
x_.load(is, ioMode);
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("SecretKey:load");
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
x_.save(os, ioMode);
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("SecretKey:save");
}
#endif
friend std::istream& operator>>(std::istream& is, SecretKey& self)
{
self.load(is, fp::detectIoMode(Fr::getIoMode(), is));

@ -1,76 +0,0 @@
#pragma once
/**
@file
@brief 192/256-bit additive homomorphic encryption by lifted-ElGamal
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/elgamal.hpp>
#include <mcl/ecparam.hpp>
namespace mcl {
#ifdef MCL_USE_AHE192
namespace ahe192 {
const mcl::EcParam& para = mcl::ecparam::NIST_P192;
typedef mcl::FpT<mcl::FpTag, 192> Fp;
typedef mcl::FpT<mcl::ZnTag, 192> Zn;
typedef mcl::EcT<Fp> Ec;
typedef mcl::ElgamalT<Ec, Zn> ElgamalEc;
typedef ElgamalEc::PrivateKey SecretKey;
typedef ElgamalEc::PublicKey PublicKey;
typedef ElgamalEc::CipherText CipherText;
static inline void initAhe()
{
Fp::init(para.p);
Zn::init(para.n);
Ec::init(para.a, para.b);
Ec::setIoMode(16);
Zn::setIoMode(16);
}
static inline void initSecretKey(SecretKey& sec)
{
const Ec P(Fp(para.gx), Fp(para.gy));
sec.init(P, Zn::getBitSize());
}
} //mcl::ahe192
#endif
#ifdef MCL_USE_AHE256
namespace ahe256 {
const mcl::EcParam& para = mcl::ecparam::NIST_P256;
typedef mcl::FpT<mcl::FpTag, 256> Fp;
typedef mcl::FpT<mcl::ZnTag, 256> Zn;
typedef mcl::EcT<Fp> Ec;
typedef mcl::ElgamalT<Ec, Zn> ElgamalEc;
typedef ElgamalEc::PrivateKey SecretKey;
typedef ElgamalEc::PublicKey PublicKey;
typedef ElgamalEc::CipherText CipherText;
static inline void initAhe()
{
Fp::init(para.p);
Zn::init(para.n);
Ec::init(para.a, para.b);
Ec::setIoMode(16);
Zn::setIoMode(16);
}
static inline void initSecretKey(SecretKey& sec)
{
const Ec P(Fp(para.gx), Fp(para.gy));
sec.init(P, Zn::getBitSize());
}
} //mcl::ahe256
#endif
} // mcl

@ -118,6 +118,7 @@ class FixedArray {
y = t;
}
public:
typedef T value_type;
FixedArray() : n_(0) {}
bool resize(size_t n)
{
@ -125,6 +126,15 @@ public:
n_ = n;
return true;
}
void push(bool *pb, const T& x)
{
if (n_ == maxSize) {
*pb = false;
return;
}
p_[n_++] = x;
*pb = true;
}
bool copy(const FixedArray<T, maxSize>& rhs)
{
if (this == &rhs) return true;

@ -75,35 +75,47 @@ typedef struct mclBnFp2 mclBnFp2;
#else
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE];
} mclBnFp;
/*
x = d[0] + d[1] i where i^2 = -1
*/
typedef struct {
mclBnFp d[2];
} mclBnFp2;
/*
G1 and G2 are isomorphism to Fr
*/
typedef struct {
uint64_t d[MCLBN_FR_UNIT_SIZE];
} mclBnFr;
/*
G1 is defined over Fp
*/
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 3];
mclBnFp x, y, z;
} mclBnG1;
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 2 * 3];
mclBnFp2 x, y, z;
} mclBnG2;
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE * 12];
mclBnFp d[12];
} mclBnGT;
typedef struct {
uint64_t d[MCLBN_FP_UNIT_SIZE];
} mclBnFp;
typedef struct {
mclBnFp d[2];
} mclBnFp2;
#endif
#include <mcl/curve_type.h>
#define MCLBN_IO_EC_AFFINE 0
#define MCLBN_IO_EC_PROJ 1024
#define MCLBN_IO_SERIALIZE_HEX_STR 2048
// for backword compatibility
enum {
mclBn_CurveFp254BNb = 0,
@ -115,7 +127,7 @@ enum {
};
// return 0xABC which means A.BC
MCLBN_DLL_API int mclBn_getVersion();
MCLBN_DLL_API int mclBn_getVersion(void);
/*
init library
@param curve [in] type of bn curve
@ -131,6 +143,7 @@ MCLBN_DLL_API int mclBn_getVersion();
*/
MCLBN_DLL_API int mclBn_init(int curve, int compiledTimeVar);
MCLBN_DLL_API int mclBn_getCurveType(void);
/*
pairing : G1 x G2 -> GT
@ -179,10 +192,20 @@ MCLBN_DLL_API mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize);
/*
set ETH serialization mode for BLS12-381
@param ETHserialization [in] 1:enable, 0:disable
@param enable [in] 1:enable, 0:disable
@note ignore the flag if curve is not BLS12-381
*/
MCLBN_DLL_API void mclBn_setETHserialization(int ETHserialization);
MCLBN_DLL_API void mclBn_setETHserialization(int enable);
// return 1 if ETH serialization mode else 0
MCLBN_DLL_API int mclBn_getETHserialization(void);
/*
set map-to-function to mode (only support MCL_MAP_TO_MODE_HASH_TO_CURVE_07)
return 0 if success else -1
*/
MCLBN_DLL_API int mclBn_setMapToMode(int mode);
////////////////////////////////////////////////
/*
deserialize
@ -238,6 +261,8 @@ MCLBN_DLL_API void mclBnFp2_clear(mclBnFp2 *x);
// set x to y
MCLBN_DLL_API void mclBnFr_setInt(mclBnFr *y, mclInt x);
MCLBN_DLL_API void mclBnFr_setInt32(mclBnFr *y, int x);
MCLBN_DLL_API void mclBnFp_setInt(mclBnFp *y, mclInt x);
MCLBN_DLL_API void mclBnFp_setInt32(mclBnFp *y, int x);
// x = buf & (1 << bitLen(r)) - 1
// if (x >= r) x &= (1 << (bitLen(r) - 1)) - 1
@ -245,25 +270,49 @@ MCLBN_DLL_API void mclBnFr_setInt32(mclBnFr *y, int x);
MCLBN_DLL_API int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize);
MCLBN_DLL_API int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize);
/*
write a value as little endian
return written size if success else 0
@note buf[0] = 0 and return 1 if the value is zero
*/
MCLBN_DLL_API mclSize mclBnFr_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFr *x);
MCLBN_DLL_API mclSize mclBnFp_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFp *x);
// set (buf mod r) to x
// return 0 if bufSize <= (byte size of Fr * 2) else -1
MCLBN_DLL_API int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize);
MCLBN_DLL_API int mclBnFr_setBigEndianMod(mclBnFr *x, const void *buf, mclSize bufSize);
// set (buf mod p) to x
// return 0 if bufSize <= (byte size of Fp * 2) else -1
MCLBN_DLL_API int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize);
MCLBN_DLL_API int mclBnFp_setBigEndianMod(mclBnFp *x, const void *buf, mclSize bufSize);
// return 1 if true and 0 otherwise
MCLBN_DLL_API int mclBnFr_isValid(const mclBnFr *x);
MCLBN_DLL_API int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y);
MCLBN_DLL_API int mclBnFr_isZero(const mclBnFr *x);
MCLBN_DLL_API int mclBnFr_isOne(const mclBnFr *x);
MCLBN_DLL_API int mclBnFr_isOdd(const mclBnFr *x);
// return 1 if half <= x < r, where half = (r + 1) / 2 else 0
MCLBN_DLL_API int mclBnFr_isNegative(const mclBnFr *x);
MCLBN_DLL_API int mclBnFp_isValid(const mclBnFp *x);
MCLBN_DLL_API int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API int mclBnFp_isZero(const mclBnFp *x);
MCLBN_DLL_API int mclBnFp_isOne(const mclBnFp *x);
MCLBN_DLL_API int mclBnFp_isOdd(const mclBnFp *x);
// return 1 if half <= x < p, where half = (p + 1) / 2 else 0
MCLBN_DLL_API int mclBnFp_isNegative(const mclBnFp *x);
MCLBN_DLL_API int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y);
MCLBN_DLL_API int mclBnFp2_isZero(const mclBnFp2 *x);
MCLBN_DLL_API int mclBnFp2_isOne(const mclBnFp2 *x);
#ifndef MCL_DONT_USE_CSRPNG
// return 0 if success
MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x);
MCLBN_DLL_API int mclBnFp_setByCSPRNG(mclBnFp *x);
/*
set user-defined random function for setByCSPRNG
@ -294,6 +343,28 @@ MCLBN_DLL_API void mclBnFr_sub(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
MCLBN_DLL_API void mclBnFr_mul(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
MCLBN_DLL_API void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y);
MCLBN_DLL_API void mclBnFp_neg(mclBnFp *y, const mclBnFp *x);
MCLBN_DLL_API void mclBnFp_inv(mclBnFp *y, const mclBnFp *x);
MCLBN_DLL_API void mclBnFp_sqr(mclBnFp *y, const mclBnFp *x);
MCLBN_DLL_API void mclBnFp_add(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API void mclBnFp_sub(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API void mclBnFp_mul(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API void mclBnFp_div(mclBnFp *z, const mclBnFp *x, const mclBnFp *y);
MCLBN_DLL_API void mclBnFp2_neg(mclBnFp2 *y, const mclBnFp2 *x);
MCLBN_DLL_API void mclBnFp2_inv(mclBnFp2 *y, const mclBnFp2 *x);
MCLBN_DLL_API void mclBnFp2_sqr(mclBnFp2 *y, const mclBnFp2 *x);
MCLBN_DLL_API void mclBnFp2_add(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
MCLBN_DLL_API void mclBnFp2_sub(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
MCLBN_DLL_API void mclBnFp2_mul(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
MCLBN_DLL_API void mclBnFp2_div(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y);
// y is one of square root of x
// return 0 if success else -1
MCLBN_DLL_API int mclBnFr_squareRoot(mclBnFr *y, const mclBnFr *x);
MCLBN_DLL_API int mclBnFp_squareRoot(mclBnFp *y, const mclBnFp *x);
MCLBN_DLL_API int mclBnFp2_squareRoot(mclBnFp2 *y, const mclBnFp2 *x);
////////////////////////////////////////////////
// set zero
MCLBN_DLL_API void mclBnG1_clear(mclBnG1 *x);
@ -365,26 +436,37 @@ MCLBN_DLL_API int mclBnGT_isZero(const mclBnGT *x);
MCLBN_DLL_API int mclBnGT_isOne(const mclBnGT *x);
MCLBN_DLL_API void mclBnGT_neg(mclBnGT *y, const mclBnGT *x);
MCLBN_DLL_API void mclBnGT_inv(mclBnGT *y, const mclBnGT *x);
MCLBN_DLL_API void mclBnGT_sqr(mclBnGT *y, const mclBnGT *x);
MCLBN_DLL_API void mclBnGT_add(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
MCLBN_DLL_API void mclBnGT_sub(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
MCLBN_DLL_API void mclBnGT_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
MCLBN_DLL_API void mclBnGT_div(mclBnGT *z, const mclBnGT *x, const mclBnGT *y);
// y = conjugate of x in Fp12, which is equal to the inverse of x if |x|^r = 1
MCLBN_DLL_API void mclBnGT_inv(mclBnGT *y, const mclBnGT *x);
// use invGeneric when x in Fp12 is not in GT
MCLBN_DLL_API void mclBnGT_invGeneric(mclBnGT *y, const mclBnGT *x);
/*
pow for all elements of Fp12
*/
MCLBN_DLL_API void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y);
/*
pow for only {x|x^r = 1} in Fp12 by GLV method
pow for only {x|x^r = 1} in GT by GLV method
the value generated by pairing satisfies the condition
*/
MCLBN_DLL_API void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y);
// z = sum_{i=0}^{n-1} x[i] y[i]
MCLBN_DLL_API void mclBnG1_mulVec(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y, mclSize n);
MCLBN_DLL_API void mclBnG2_mulVec(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y, mclSize n);
MCLBN_DLL_API void mclBnGT_powVec(mclBnGT *z, const mclBnGT *x, const mclBnFr *y, mclSize n);
MCLBN_DLL_API void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
MCLBN_DLL_API void mclBn_finalExp(mclBnGT *y, const mclBnGT *x);
MCLBN_DLL_API void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y);
// z = prod_{i=0}^{n-1} millerLoop(x[i], y[i])
MCLBN_DLL_API void mclBn_millerLoopVec(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y, mclSize n);
// return precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t)
MCLBN_DLL_API int mclBn_getUint64NumToPrecompute(void);
@ -410,7 +492,8 @@ MCLBN_DLL_API int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVe
/*
evaluate polynomial
out = f(x) = c[0] + c[1] * x + c[2] * x^2 + ... + c[cSize - 1] * x^(cSize - 1)
@note cSize >= 2
return 0 if success else -1
@note cSize >= 1
*/
MCLBN_DLL_API int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, mclSize cSize, const mclBnFr *x);
MCLBN_DLL_API int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, mclSize cSize, const mclBnFr *x);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,34 @@
#pragma once
/**
@file
@brief constant macro
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <cybozu/inttype.hpp>
#ifndef MCL_SIZEOF_UNIT
#if defined(CYBOZU_OS_BIT) && (CYBOZU_OS_BIT == 32)
#define MCL_SIZEOF_UNIT 4
#else
#define MCL_SIZEOF_UNIT 8
#endif
#endif
#ifndef MCL_MAX_BIT_SIZE
#define MCL_MAX_BIT_SIZE 512
#endif
namespace mcl {
namespace fp {
#if MCL_SIZEOF_UNIT == 8
typedef uint64_t Unit;
#else
typedef uint32_t Unit;
#endif
#define MCL_UNIT_BIT_SIZE (MCL_SIZEOF_UNIT * 8)
} } // mcl::fp

@ -1,6 +1,7 @@
#pragma once
#include <cybozu/itoa.hpp>
#include <cybozu/stream.hpp>
#include <mcl/config.hpp>
/**
@file
@brief convertion bin/dec/hex <=> array
@ -15,6 +16,44 @@
namespace mcl { namespace fp {
/*
treat src[] as a little endian and set dst[]
fill remain of dst if sizeof(D) * dstN > sizeof(S) * srcN
return false if sizeof(D) * dstN < sizeof(S) * srcN
*/
template<class D, class S>
bool convertArrayAsLE(D *dst, size_t dstN, const S *src, size_t srcN)
{
char assert_D_is_unsigned[D(-1) < 0 ? -1 : 1];
char assert_S_is_unsigned[S(-1) < 0 ? -1 : 1];
(void)assert_D_is_unsigned;
(void)assert_S_is_unsigned;
if (sizeof(D) * dstN < sizeof(S) * srcN) return false;
size_t pos = 0;
if (sizeof(D) < sizeof(S)) {
for (size_t i = 0; i < srcN; i++) {
S s = src[i];
for (size_t j = 0; j < sizeof(S); j += sizeof(D)) {
dst[pos++] = D(s);
s >>= sizeof(D) * 8;
}
}
for (; pos < dstN; pos++) {
dst[pos] = 0;
}
} else {
for (size_t i = 0; i < dstN; i++) {
D u = 0;
for (size_t j = 0; j < sizeof(D); j += sizeof(S)) {
S s = (pos < srcN) ? src[pos++] : 0;
u |= D(s) << (j * 8);
}
dst[i] = u;
}
}
return true;
}
namespace local {
inline bool isSpace(char c)
@ -208,8 +247,6 @@ inline bool parsePrefix(size_t *readSize, bool *isMinus, int *base, const char *
if (*base == 0 || *base == 2) {
*base = 2;
pos += 2;
} else {
return false;
}
}
}
@ -337,31 +374,22 @@ inline size_t binToArray(UT *x, size_t maxN, const char *buf, size_t bufSize)
}
/*
little endian x[0, xn) to buf
little endian t[0, tn) to buf
return written size if success else 0
data is buf[bufSize - retval, bufSize)
*/
template<class UT>
inline size_t arrayToDec(char *buf, size_t bufSize, const UT *x, size_t xn)
inline size_t inner_arrayToDec(char *buf, size_t bufSize, uint32_t *t, size_t tn)
{
const size_t maxN = 64;
uint32_t t[maxN];
if (sizeof(UT) == 8) {
xn *= 2;
}
if (xn > maxN) return 0;
memcpy(t, x, xn * sizeof(t[0]));
const size_t width = 9;
const uint32_t i1e9 = 1000000000U;
size_t pos = 0;
for (;;) {
uint32_t r = local::divU32(t, t, xn, i1e9);
while (xn > 0 && t[xn - 1] == 0) xn--;
uint32_t r = local::divU32(t, t, tn, i1e9);
while (tn > 0 && t[tn - 1] == 0) tn--;
size_t len = cybozu::itoa_local::uintToDec(buf, bufSize - pos, r);
if (len == 0) return 0;
assert(0 < len && len <= width);
if (xn == 0) return pos + len;
if (tn == 0) return pos + len;
// fill (width - len) '0'
for (size_t j = 0; j < width - len; j++) {
buf[bufSize - pos - width + j] = '0';
@ -370,21 +398,33 @@ inline size_t arrayToDec(char *buf, size_t bufSize, const UT *x, size_t xn)
}
}
inline size_t arrayToDec(char *buf, size_t bufSize, const uint32_t *x, size_t xn)
{
uint32_t *t = (uint32_t*)CYBOZU_ALLOCA(sizeof(uint32_t) * xn);
memcpy(t, x, sizeof(uint32_t) * xn);
return inner_arrayToDec(buf, bufSize, t, xn);
}
inline size_t arrayToDec(char *buf, size_t bufSize, const uint64_t *x, size_t xn)
{
uint32_t *t = (uint32_t*)CYBOZU_ALLOCA(sizeof(uint32_t) * xn * 2);
for (size_t i = 0; i < xn; i++) {
uint64_t v = x[i];
t[i * 2 + 0] = uint32_t(v);
t[i * 2 + 1] = uint32_t(v >> 32);
}
return inner_arrayToDec(buf, bufSize, t, xn * 2);
}
/*
convert buf[0, bufSize) to x[0, num)
return written num if success else 0
*/
template<class UT>
inline size_t decToArray(UT *_x, size_t maxN, const char *buf, size_t bufSize)
inline size_t decToArray(uint32_t *x, size_t maxN, const char *buf, size_t bufSize)
{
assert(sizeof(UT) == 4 || sizeof(UT) == 8);
const size_t width = 9;
const uint32_t i1e9 = 1000000000U;
if (maxN == 0) return 0;
if (sizeof(UT) == 8) {
maxN *= 2;
}
uint32_t *x = reinterpret_cast<uint32_t*>(_x);
size_t xn = 1;
x[0] = 0;
while (bufSize > 0) {
@ -406,10 +446,20 @@ inline size_t decToArray(UT *_x, size_t maxN, const char *buf, size_t bufSize)
buf += n;
bufSize -= n;
}
if (sizeof(UT) == 8 && (xn & 1)) {
x[xn++] = 0;
return xn;
}
inline size_t decToArray(uint64_t *x, size_t maxN, const char *buf, size_t bufSize)
{
uint32_t *t = (uint32_t*)CYBOZU_ALLOCA(sizeof(uint32_t) * maxN * 2);
size_t xn = decToArray(t, maxN * 2, buf, bufSize);
if (xn & 1) {
t[xn++] = 0;
}
for (size_t i = 0; i < xn; i += 2) {
x[i / 2] = (uint64_t(t[i + 1]) << 32) | t[i];
}
return xn / (sizeof(UT) / 4);
return xn / 2;
}
/*

@ -18,7 +18,7 @@ enum {
/*
for only G1
the size of curve must be less or equal to MCLBN_FP_UNIT_SIZE
the size of curve must be <= MCLBN_FP_UNIT_SIZE
*/
MCL_EC_BEGIN = 100,
MCL_SECP192K1 = MCL_EC_BEGIN,
@ -29,7 +29,90 @@ enum {
MCL_NIST_P192 = 105,
MCL_NIST_P224 = 106,
MCL_NIST_P256 = 107,
MCL_EC_END = MCL_NIST_P256 + 1,
MCL_SECP160K1 = 108,
MCL_P160_1 = 109,
MCL_EC_END = MCL_P160_1 + 1,
MCL_NIST_P384 = MCL_SECP384R1,
MCL_NIST_P521 = MCL_SECP521R1
};
/*
remark : if irtf-cfrg-hash-to-curve is compeletely fixed, then
MCL_MAP_TO_MODE_WB19, MCL_MAP_TO_MODE_HASH_TO_CURVE_0? will be removed and
only MCL_MAP_TO_MODE_HASH_TO_CURVE will be available.
*/
enum {
MCL_MAP_TO_MODE_ORIGINAL, // see MapTo::calcBN
MCL_MAP_TO_MODE_TRY_AND_INC, // try-and-incremental-x
MCL_MAP_TO_MODE_ETH2, // (deprecated) old eth2.0 spec
MCL_MAP_TO_MODE_WB19, // (deprecated) used in new eth2.0 spec
MCL_MAP_TO_MODE_HASH_TO_CURVE_05 = MCL_MAP_TO_MODE_WB19, // (deprecated) draft-irtf-cfrg-hash-to-curve-05
MCL_MAP_TO_MODE_HASH_TO_CURVE_06, // (deprecated) draft-irtf-cfrg-hash-to-curve-06
MCL_MAP_TO_MODE_HASH_TO_CURVE_07, // draft-irtf-cfrg-hash-to-curve-07
MCL_MAP_TO_MODE_HASH_TO_CURVE = MCL_MAP_TO_MODE_HASH_TO_CURVE_07 // the latset version
};
#ifdef __cplusplus
#include <string.h>
#include <assert.h>
namespace mcl {
struct CurveParam {
/*
y^2 = x^3 + b
i^2 = -1
xi = xi_a + i
v^3 = xi
w^2 = v
*/
const char *z;
int b; // y^2 = x^3 + b
int xi_a; // xi = xi_a + i
/*
BN254, BN381 : Dtype
BLS12-381 : Mtype
*/
bool isMtype;
int curveType; // same in curve_type.h
bool operator==(const CurveParam& rhs) const
{
return strcmp(z, rhs.z) == 0 && b == rhs.b && xi_a == rhs.xi_a && isMtype == rhs.isMtype;
}
bool operator!=(const CurveParam& rhs) const { return !operator==(rhs); }
};
const CurveParam BN254 = { "-0x4080000000000001", 2, 1, false, MCL_BN254 }; // -(2^62 + 2^55 + 1)
// provisional(experimental) param with maxBitSize = 384
const CurveParam BN381_1 = { "-0x400011000000000000000001", 2, 1, false, MCL_BN381_1 }; // -(2^94 + 2^76 + 2^72 + 1) // A Family of Implementation-Friendly BN Elliptic Curves
const CurveParam BN381_2 = { "-0x400040090001000000000001", 2, 1, false, MCL_BN381_2 }; // -(2^94 + 2^78 + 2^67 + 2^64 + 2^48 + 1) // used in relic-toolkit
const CurveParam BN462 = { "0x4001fffffffffffffffffffffbfff", 5, 2, false, MCL_BN462 }; // 2^114 + 2^101 - 2^14 - 1 // https://eprint.iacr.org/2017/334
const CurveParam BN_SNARK1 = { "4965661367192848881", 3, 9, false, MCL_BN_SNARK1 };
const CurveParam BLS12_381 = { "-0xd201000000010000", 4, 1, true, MCL_BLS12_381 };
const CurveParam BN160 = { "0x4000000031", 3, 4, false, MCL_BN160 };
#ifdef __clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
#endif
inline const CurveParam* getCurveParam(int type)
{
switch (type) {
case MCL_BN254: return &mcl::BN254;
case MCL_BN381_1: return &mcl::BN381_1;
case MCL_BN381_2: return &mcl::BN381_2;
case MCL_BN462: return &mcl::BN462;
case MCL_BN_SNARK1: return &mcl::BN_SNARK1;
case MCL_BLS12_381: return &mcl::BLS12_381;
case MCL_BN160: return &mcl::BN160;
default:
return 0;
}
}
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
} // mcl
#endif

File diff suppressed because it is too large Load Diff

@ -1,105 +0,0 @@
#pragma once
/**
@file
@brief C interface of ECDSA
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <stdint.h> // for uint64_t, uint8_t
#include <stdlib.h> // for size_t
#if defined(_MSC_VER)
#ifdef ECDSA_DLL_EXPORT
#define ECDSA_DLL_API __declspec(dllexport)
#else
#define ECDSA_DLL_API __declspec(dllimport)
#ifndef ECDSA_NO_AUTOLINK
#pragma comment(lib, "mclecdsa.lib")
#endif
#endif
#elif defined(__EMSCRIPTEN__)
#define ECDSA_DLL_API __attribute__((used))
#else
#define ECDSA_DLL_API
#endif
#ifndef mclSize
#ifdef __EMSCRIPTEN__
// avoid 64-bit integer
#define mclSize unsigned int
#define mclInt int
#else
// use #define for cgo
#define mclSize size_t
#define mclInt int64_t
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef ECDSA_NOT_DEFINE_STRUCT
typedef struct ecdsaSecretKey ecdsaSecretKey;
typedef struct ecdsaPublicKey ecdsaPublicKey;
typedef struct ecdsaSignature ecdsaSignature;
#else
typedef struct {
uint64_t d[4];
} ecdsaSecretKey;
typedef struct {
uint64_t d[4 * 3];
} ecdsaPublicKey;
typedef struct {
uint64_t d[4 * 2];
} ecdsaSignature;
#endif
struct ecdsaPrecomputedPublicKey;
/*
init library
return 0 if success
@note not threadsafe
*/
ECDSA_DLL_API int ecdsaInit(void);
// return written byte size if success else 0
ECDSA_DLL_API mclSize ecdsaSecretKeySerialize(void *buf, mclSize maxBufSize, const ecdsaSecretKey *sec);
ECDSA_DLL_API mclSize ecdsaPublicKeySerialize(void *buf, mclSize maxBufSize, const ecdsaPublicKey *pub);
ECDSA_DLL_API mclSize ecdsaSignatureSerialize(void *buf, mclSize maxBufSize, const ecdsaSignature *sig);
// return read byte size if sucess else 0
ECDSA_DLL_API mclSize ecdsaSecretKeyDeserialize(ecdsaSecretKey* sec, const void *buf, mclSize bufSize);
ECDSA_DLL_API mclSize ecdsaPublicKeyDeserialize(ecdsaPublicKey* pub, const void *buf, mclSize bufSize);
ECDSA_DLL_API mclSize ecdsaSignatureDeserialize(ecdsaSignature* sig, const void *buf, mclSize bufSize);
// return 0 if success
ECDSA_DLL_API int ecdsaSecretKeySetByCSPRNG(ecdsaSecretKey *sec);
ECDSA_DLL_API void ecdsaGetPublicKey(ecdsaPublicKey *pub, const ecdsaSecretKey *sec);
ECDSA_DLL_API void ecdsaSign(ecdsaSignature *sig, const ecdsaSecretKey *sec, const void *m, mclSize size);
// return 1 if valid
ECDSA_DLL_API int ecdsaVerify(const ecdsaSignature *sig, const ecdsaPublicKey *pub, const void *m, mclSize size);
ECDSA_DLL_API int ecdsaVerifyPrecomputed(const ecdsaSignature *sig, const ecdsaPrecomputedPublicKey *pub, const void *m, mclSize size);
// return nonzero if success
ECDSA_DLL_API ecdsaPrecomputedPublicKey *ecdsaPrecomputedPublicKeyCreate();
// call this function to avoid memory leak
ECDSA_DLL_API void ecdsaPrecomputedPublicKeyDestroy(ecdsaPrecomputedPublicKey *ppub);
// return 0 if success
ECDSA_DLL_API int ecdsaPrecomputedPublicKeyInit(ecdsaPrecomputedPublicKey *ppub, const ecdsaPublicKey *pub);
#ifdef __cplusplus
}
#endif

@ -1,257 +0,0 @@
#pragma once
/**
@file
@brief ECDSA
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/fp.hpp>
#include <mcl/ec.hpp>
#include <mcl/ecparam.hpp>
#include <mcl/window_method.hpp>
namespace mcl { namespace ecdsa {
namespace local {
#ifndef MCLSHE_WIN_SIZE
#define MCLSHE_WIN_SIZE 10
#endif
static const size_t winSize = MCLSHE_WIN_SIZE;
struct FpTag;
struct ZnTag;
} // mcl::ecdsa::local
typedef mcl::FpT<local::FpTag, 256> Fp;
typedef mcl::FpT<local::ZnTag, 256> Zn;
typedef mcl::EcT<Fp> Ec;
namespace local {
struct Param {
mcl::EcParam ecParam;
Ec P;
mcl::fp::WindowMethod<Ec> Pbase;
};
inline Param& getParam()
{
static Param p;
return p;
}
inline void be32toZn(Zn& x, const mcl::fp::Unit *buf)
{
const size_t n = 32;
const unsigned char *p = (const unsigned char*)buf;
unsigned char be[n];
for (size_t i = 0; i < n; i++) {
be[i] = p[n - 1 - i];
}
x.setArrayMaskMod(be, n);
}
/*
y = x mod n
*/
inline void FpToZn(Zn& y, const Fp& x)
{
fp::Block b;
x.getBlock(b);
y.setArrayMaskMod(b.p, b.n);
}
inline void setHashOf(Zn& x, const void *msg, size_t msgSize)
{
mcl::fp::Unit xBuf[256 / 8 / sizeof(mcl::fp::Unit)];
uint32_t hashSize = mcl::fp::sha256(xBuf, sizeof(xBuf), msg, (uint32_t)msgSize);
assert(hashSize == sizeof(xBuf));
(void)hashSize;
be32toZn(x, xBuf);
}
} // mcl::ecdsa::local
const local::Param& param = local::getParam();
inline void init(bool *pb)
{
const mcl::EcParam& ecParam = mcl::ecparam::secp256k1;
Zn::init(pb, ecParam.n);
if (!*pb) return;
Fp::init(pb, ecParam.p);
if (!*pb) return;
Ec::init(pb, ecParam.a, ecParam.b);
if (!*pb) return;
Zn::setIoMode(16);
Fp::setIoMode(16);
Ec::setIoMode(mcl::IoEcAffine);
local::Param& p = local::getParam();
p.ecParam = ecParam;
Fp x, y;
x.setStr(pb, ecParam.gx);
if (!*pb) return;
y.setStr(pb, ecParam.gy);
if (!*pb) return;
p.P.set(pb, x, y);
if (!*pb) return;
p.Pbase.init(pb, p.P, ecParam.bitSize, local::winSize);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
inline void init()
{
bool b;
init(&b);
if (!b) throw cybozu::Exception("ecdsa:init");
}
#endif
typedef Zn SecretKey;
typedef Ec PublicKey;
struct PrecomputedPublicKey {
mcl::fp::WindowMethod<Ec> pubBase_;
void init(bool *pb, const PublicKey& pub)
{
pubBase_.init(pb, pub, param.ecParam.bitSize, local::winSize);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
void init(const PublicKey& pub)
{
bool b;
init(&b, pub);
if (!b) throw cybozu::Exception("ecdsa:PrecomputedPublicKey:init");
}
#endif
};
inline void getPublicKey(PublicKey& pub, const SecretKey& sec)
{
Ec::mul(pub, param.P, sec);
pub.normalize();
}
struct Signature : public mcl::fp::Serializable<Signature> {
Zn r, s;
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
r.load(pb, is, ioMode); if (!*pb) return;
s.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
const char sep = *fp::getIoSeparator(ioMode);
r.save(pb, os, ioMode); if (!*pb) return;
if (sep) {
cybozu::writeChar(pb, os, sep);
if (!*pb) return;
}
s.save(pb, os, ioMode);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
bool b;
load(&b, is, ioMode);
if (!b) throw cybozu::Exception("ecdsa:Signature:load");
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
bool b;
save(&b, os, ioMode);
if (!b) throw cybozu::Exception("ecdsa:Signature:save");
}
#endif
#ifndef CYBOZU_DONT_USE_STRING
friend std::istream& operator>>(std::istream& is, Signature& self)
{
self.load(is, fp::detectIoMode(Ec::getIoMode(), is));
return is;
}
friend std::ostream& operator<<(std::ostream& os, const Signature& self)
{
self.save(os, fp::detectIoMode(Ec::getIoMode(), os));
return os;
}
#endif
};
inline void sign(Signature& sig, const SecretKey& sec, const void *msg, size_t msgSize)
{
Zn& r = sig.r;
Zn& s = sig.s;
Zn z, k;
local::setHashOf(z, msg, msgSize);
Ec Q;
for (;;) {
k.setByCSPRNG();
param.Pbase.mul(Q, k);
if (Q.isZero()) continue;
Q.normalize();
local::FpToZn(r, Q.x);
if (r.isZero()) continue;
Zn::mul(s, r, sec);
s += z;
if (s.isZero()) continue;
s /= k;
return;
}
}
namespace local {
inline void mulDispatch(Ec& Q, const PublicKey& pub, const Zn& y)
{
Ec::mul(Q, pub, y);
}
inline void mulDispatch(Ec& Q, const PrecomputedPublicKey& ppub, const Zn& y)
{
ppub.pubBase_.mul(Q, y);
}
template<class Pub>
inline bool verify(const Signature& sig, const Pub& pub, const void *msg, size_t msgSize)
{
const Zn& r = sig.r;
const Zn& s = sig.s;
if (r.isZero() || s.isZero()) return false;
Zn z, w, u1, u2;
local::setHashOf(z, msg, msgSize);
Zn::inv(w, s);
Zn::mul(u1, z, w);
Zn::mul(u2, r, w);
Ec Q1, Q2;
param.Pbase.mul(Q1, u1);
// Ec::mul(Q2, pub, u2);
local::mulDispatch(Q2, pub, u2);
Q1 += Q2;
if (Q1.isZero()) return false;
Q1.normalize();
Zn x;
local::FpToZn(x, Q1.x);
return r == x;
}
} // mcl::ecdsa::local
inline bool verify(const Signature& sig, const PublicKey& pub, const void *msg, size_t msgSize)
{
return local::verify(sig, pub, msg, msgSize);
}
inline bool verify(const Signature& sig, const PrecomputedPublicKey& ppub, const void *msg, size_t msgSize)
{
return local::verify(sig, ppub, msg, msgSize);
}
} } // mcl::ecdsa

@ -6,10 +6,23 @@
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <mcl/ec.hpp>
#include <mcl/curve_type.h>
namespace mcl { namespace ecparam {
namespace mcl {
struct EcParam {
const char *name;
const char *p;
const char *a;
const char *b;
const char *gx;
const char *gy;
const char *n;
size_t bitSize; // bit length of p
int curveType;
};
namespace ecparam {
const struct mcl::EcParam secp160k1 = {
"secp160k1",
@ -20,9 +33,9 @@ const struct mcl::EcParam secp160k1 = {
"0x938cf935318fdced6bc28286531733c3f03c4fee",
"0x100000000000000000001b8fa16dfab9aca16b6b3",
160,
-1
MCL_SECP160K1
};
// p=2^160 + 7
// p=2^160 + 7 (for test)
const struct mcl::EcParam p160_1 = {
"p160_1",
"0x10000000000000000000000000000000000000007",
@ -32,7 +45,7 @@ const struct mcl::EcParam p160_1 = {
"1236612389951462151661156731535316138439983579284",
"1461501637330902918203683518218126812711137002561",
161,
-1
MCL_P160_1
};
const struct mcl::EcParam secp192k1 = {
"secp192k1",
@ -181,11 +194,16 @@ inline const mcl::EcParam* getEcParam(int curve)
case MCL_SECP224K1: return &ecparam::secp224k1;
case MCL_SECP256K1: return &ecparam::secp256k1;
case MCL_SECP384R1: return &ecparam::secp384r1;
case MCL_SECP521R1: return &ecparam::secp521r1;
case MCL_NIST_P192: return &ecparam::NIST_P192;
case MCL_NIST_P224: return &ecparam::NIST_P224;
case MCL_NIST_P256: return &ecparam::NIST_P256;
case MCL_SECP160K1: return &ecparam::secp160k1;
case MCL_P160_1: return &ecparam::p160_1;
default: return 0;
}
}
} // mcl
#include <mcl/ec.hpp>

@ -386,7 +386,7 @@ struct ElgamalT {
create table g^i for i in [rangeMin, rangeMax]
*/
struct PowerCache {
#if (CYBOZU_CPP_VERSION > CYBOZU_CPP_VERSION_CP03)
#if (CYBOZU_CPP_VERSION > CYBOZU_CPP_VERSION_CPP03)
typedef CYBOZU_NAMESPACE_STD::unordered_map<Ec, int> Cache;
#else
typedef std::map<Ec, int> Cache;

@ -38,13 +38,6 @@ struct ZnTag;
namespace fp {
// copy src to dst as little endian
void copyUnitToByteAsLE(uint8_t *dst, const Unit *src, size_t byteSize);
// copy src to dst as little endian
void copyByteToUnitAsLE(Unit *dst, const uint8_t *src, size_t byteSize);
bool copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, MaskMode maskMode);
uint64_t getUint64(bool *pb, const fp::Block& b);
int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op);
@ -73,13 +66,15 @@ bool isEnableJIT(); // 1st call is not threadsafe
uint32_t sha256(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);
uint32_t sha512(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);
// draft-07 outSize = 128 or 256
void expand_message_xmd(uint8_t out[], size_t outSize, const void *msg, size_t msgSize, const void *dst, size_t dstSize);
namespace local {
inline void byteSwap(void *x, size_t n)
inline void byteSwap(uint8_t *x, size_t n)
{
char *p = (char *)x;
for (size_t i = 0; i < n / 2; i++) {
fp::swap_(p[i], p[n - 1 - i]);
fp::swap_(x[i], x[n - 1 - i]);
}
}
@ -105,6 +100,47 @@ private:
template<class Fp> friend class FpDblT;
template<class Fp> friend class Fp2T;
template<class Fp> friend struct Fp6T;
#ifdef MCL_XBYAK_DIRECT_CALL
static inline void addA(Unit *z, const Unit *x, const Unit *y)
{
op_.fp_add(z, x, y, op_.p);
}
static inline void subA(Unit *z, const Unit *x, const Unit *y)
{
op_.fp_sub(z, x, y, op_.p);
}
static inline void negA(Unit *y, const Unit *x)
{
op_.fp_neg(y, x, op_.p);
}
static inline void mulA(Unit *z, const Unit *x, const Unit *y)
{
op_.fp_mul(z, x, y, op_.p);
}
static inline void sqrA(Unit *y, const Unit *x)
{
op_.fp_sqr(y, x, op_.p);
}
static inline void mul2A(Unit *y, const Unit *x)
{
op_.fp_mul2(y, x, op_.p);
}
#endif
static inline void mul9A(Unit *y, const Unit *x)
{
mulSmall(y, x, 9);
// op_.fp_mul9(y, x, op_.p);
}
static inline void mulSmall(Unit *z, const Unit *x, const uint32_t y)
{
assert(y <= op_.smallModp.maxMulN);
Unit xy[maxSize + 1];
op_.fp_mulUnitPre(xy, x, y);
int v = op_.smallModp.approxMul(xy);
const Unit *pv = op_.smallModp.getPmul(v);
op_.fp_subPre(z, xy, pv);
op_.fp_sub(z, z, op_.p, op_.p);
}
public:
typedef FpT<tag, maxBitSize> BaseFp;
// return pointer to array v_[]
@ -115,6 +151,7 @@ public:
static inline size_t getBitSize() { return op_.bitSize; }
static inline size_t getByteSize() { return (op_.bitSize + 7) / 8; }
static inline const fp::Op& getOp() { return op_; }
static inline fp::Op& getOpNonConst() { return op_; }
void dump() const
{
const size_t N = op_.N;
@ -131,6 +168,9 @@ public:
{
assert(maxBitSize <= MCL_MAX_BIT_SIZE);
*pb = op_.init(p, maxBitSize, xi_a, mode);
#ifdef MCL_DUMP_JIT
return;
#endif
if (!*pb) return;
{ // set oneRep
FpT& one = *reinterpret_cast<FpT*>(op_.oneRep);
@ -147,16 +187,27 @@ public:
ioMode_ = 0;
isETHserialization_ = false;
#ifdef MCL_XBYAK_DIRECT_CALL
add = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_addA_);
if (add == 0) add = addC;
sub = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_subA_);
if (sub == 0) sub = subC;
neg = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_negA_);
if (neg == 0) neg = negC;
mul = fp::func_ptr_cast<void (*)(FpT& z, const FpT& x, const FpT& y)>(op_.fp_mulA_);
if (mul == 0) mul = mulC;
sqr = fp::func_ptr_cast<void (*)(FpT& y, const FpT& x)>(op_.fp_sqrA_);
if (sqr == 0) sqr = sqrC;
if (op_.fp_addA_ == 0) {
op_.fp_addA_ = addA;
}
if (op_.fp_subA_ == 0) {
op_.fp_subA_ = subA;
}
if (op_.fp_negA_ == 0) {
op_.fp_negA_ = negA;
}
if (op_.fp_mulA_ == 0) {
op_.fp_mulA_ = mulA;
}
if (op_.fp_sqrA_ == 0) {
op_.fp_sqrA_ = sqrA;
}
if (op_.fp_mul2A_ == 0) {
op_.fp_mul2A_ = mul2A;
}
if (op_.fp_mul9A_ == 0) {
op_.fp_mul9A_ = mul9A;
}
#endif
*pb = true;
}
@ -224,7 +275,7 @@ public:
} else {
clear();
if (x) {
int64_t y = x < 0 ? -x : x;
uint64_t y = fp::abs_(x);
if (sizeof(Unit) == 8) {
v_[0] = y;
} else {
@ -254,26 +305,28 @@ public:
{
if (isMont()) op_.fromMont(v_, v_);
}
// deny a string with large length even if the value is in Fp
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode)
{
bool isMinus = false;
*pb = false;
if (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) {
if (fp::isIoSerializeMode(ioMode)) {
const size_t n = getByteSize();
v_[op_.N - 1] = 0;
uint8_t *buf = (uint8_t*)CYBOZU_ALLOCA(n);
size_t readSize;
if (ioMode & IoSerializeHexStr) {
readSize = mcl::fp::readHexStr(v_, n, is);
readSize = mcl::fp::readHexStr(buf, n, is);
} else {
readSize = cybozu::readSome(v_, n, is);
readSize = cybozu::readSome(buf, n, is);
}
if (readSize != n) return;
if (isETHserialization_ && ioMode & (IoSerialize | IoSerializeHexStr)) {
fp::local::byteSwap(v_, n);
fp::local::byteSwap(buf, n);
}
if (readSize != n) return;
fp::convertArrayAsLE(v_, op_.N, buf, n);
} else {
char buf[1024];
char buf[sizeof(*this) * 8 + 2]; // '0b' + max binary format length
size_t n = fp::local::loadWord(buf, sizeof(buf), is);
if (n == 0) return;
n = fp::strToArray(&isMinus, v_, op_.N, buf, n, ioMode);
@ -295,24 +348,23 @@ public:
void save(bool *pb, OutputStream& os, int ioMode) const
{
const size_t n = getByteSize();
if (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) {
if (fp::isIoSerializeMode(ioMode)) {
const size_t xn = sizeof(fp::Unit) * op_.N;
uint8_t *x = (uint8_t*)CYBOZU_ALLOCA(xn);
if (ioMode & IoArrayRaw) {
cybozu::write(pb, os, v_, n);
fp::convertArrayAsLE(x, xn, v_, op_.N);
cybozu::write(pb, os, x, n);
} else {
fp::Block b;
getBlock(b);
const char *src = (const char *)b.p;
char rev[fp::maxUnitSize * sizeof(fp::Unit)];
fp::convertArrayAsLE(x, xn, b.p, b.n);
if (isETHserialization_ && ioMode & (IoSerialize | IoSerializeHexStr)) {
for (size_t i = 0; i < n; i++) {
rev[i] = src[n - 1 - i];
}
src = rev;
fp::local::byteSwap(x, n);
}
if (ioMode & IoSerializeHexStr) {
mcl::fp::writeHexStr(pb, os, src, n);
mcl::fp::writeHexStr(pb, os, x, n);
} else {
cybozu::write(pb, os, src, n);
cybozu::write(pb, os, x, n);
}
}
return;
@ -329,31 +381,65 @@ public:
cybozu::write(pb, os, buf + sizeof(buf) - len, len);
}
/*
mode = Mod : set x mod p if sizeof(S) * n <= 64 else error
treat x as little endian
if x >= p then error
*/
template<class S>
void setArray(bool *pb, const S *x, size_t n, mcl::fp::MaskMode mode = fp::NoMask)
void setArray(bool *pb, const S *x, size_t n)
{
*pb = fp::copyAndMask(v_, x, sizeof(S) * n, op_, mode);
if (!fp::convertArrayAsLE(v_, op_.N, x, n)) {
*pb = false;
return;
}
if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) {
*pb = false;
return;
}
*pb = true;
toMont();
}
/*
mask x with (1 << bitLen) and subtract p if x >= p
treat x as little endian
x &= (1 << bitLen) = 1
x &= (1 << (bitLen - 1)) - 1 if x >= p
*/
template<class S>
void setArrayMaskMod(const S *x, size_t n)
void setArrayMask(const S *x, size_t n)
{
fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::MaskAndMod);
const size_t dstByte = sizeof(fp::Unit) * op_.N;
if (sizeof(S) * n > dstByte) {
n = dstByte / sizeof(S);
}
bool b = fp::convertArrayAsLE(v_, op_.N, x, n);
assert(b);
(void)b;
fp::maskArray(v_, op_.N, op_.bitSize);
if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) {
fp::maskArray(v_, op_.N, op_.bitSize - 1);
}
toMont();
}
/*
mask x with (1 << (bitLen - 1)) - 1 if x >= p
set (x as little endian) % p
error if size of x >= sizeof(Fp) * 2
*/
template<class S>
void setArrayMask(const S *x, size_t n)
void setArrayMod(bool *pb, const S *x, size_t n)
{
fp::copyAndMask(v_, x, sizeof(S) * n, op_, fp::SmallMask);
if (sizeof(S) * n > sizeof(fp::Unit) * op_.N * 2) {
*pb = false;
return;
}
mpz_class mx;
gmp::setArray(pb, mx, x, n);
if (!*pb) return;
#ifdef MCL_USE_VINT
op_.modp.modp(mx, mx);
#else
mx %= op_.mp;
#endif
gmp::getArray(pb, v_, op_.N, mx);
if (!*pb) return;
toMont();
}
void getBlock(fp::Block& b) const
@ -366,14 +452,82 @@ public:
b.p = &v_[0];
}
}
/*
write a value with little endian
write buf[0] = 0 and return 1 if the value is 0
return written size if success else 0
*/
size_t getLittleEndian(uint8_t *buf, size_t maxN) const
{
fp::Block b;
getBlock(b);
size_t n = sizeof(fp::Unit) * b.n;
uint8_t *t = (uint8_t*)CYBOZU_ALLOCA(n);
if (!fp::convertArrayAsLE(t, n, b.p, b.n)) {
return 0;
}
while (n > 0) {
if (t[n - 1]) break;
n--;
}
if (n == 0) n = 1; // zero
if (maxN < n) return 0;
for (size_t i = 0; i < n; i++) {
buf[i] = t[i];
}
return n;
}
/*
set (little endian % p)
error if xn > 64
*/
void setLittleEndianMod(bool *pb, const uint8_t *x, size_t xn)
{
if (xn > 64) {
*pb = false;
return;
}
setArrayMod(pb, x, xn);
}
/*
set (big endian % p)
error if xn > 64
*/
void setBigEndianMod(bool *pb, const uint8_t *x, size_t xn)
{
if (xn > 64) {
*pb = false;
return;
}
uint8_t swapX[64];
for (size_t i = 0; i < xn; i++) {
swapX[xn - 1 - i] = x[i];
}
setArrayMod(pb, swapX, xn);
}
void setByCSPRNG(bool *pb, fp::RandGen rg = fp::RandGen())
{
if (rg.isZero()) rg = fp::RandGen::get();
rg.read(pb, v_, op_.N * sizeof(Unit)); // byte size
uint8_t x[sizeof(*this)];
const size_t n = op_.N * sizeof(Unit);
rg.read(pb, x, n); // byte size
if (!pb) return;
fp::convertArrayAsLE(v_, op_.N, x, n);
setArrayMask(v_, op_.N);
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
void setLittleEndianMod(const uint8_t *buf, size_t bufSize)
{
bool b;
setLittleEndianMod(&b, buf, bufSize);
if (!b) throw cybozu::Exception("setLittleEndianMod");
}
void setBigEndianMod(const uint8_t *buf, size_t bufSize)
{
bool b;
setBigEndianMod(&b, buf, bufSize);
if (!b) throw cybozu::Exception("setBigEndianMod");
}
void setByCSPRNG(fp::RandGen rg = fp::RandGen())
{
bool b;
@ -386,11 +540,15 @@ public:
setByCSPRNG(rg);
}
/*
hash msg and mask with (1 << (bitLen - 1)) - 1
x = SHA-256(msg) as little endian
p = order of a finite field
L = bit size of p
x &= (1 << L) - 1
if (x >= p) x &= (1 << (L - 1)) - 1
*/
void setHashOf(const void *msg, size_t msgSize)
{
char buf[MCL_MAX_HASH_BIT_SIZE / 8];
uint8_t buf[MCL_MAX_HASH_BIT_SIZE / 8];
uint32_t size = op_.hash(buf, static_cast<uint32_t>(sizeof(buf)), msg, static_cast<uint32_t>(msgSize));
setArrayMask(buf, size);
}
@ -408,32 +566,78 @@ public:
}
setArray(pb, gmp::getUnit(x), gmp::getUnitSize(x));
}
static void add(FpT& z, const FpT& x, const FpT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_addA_(z.v_, x.v_, y.v_);
#else
op_.fp_add(z.v_, x.v_, y.v_, op_.p);
#endif
}
static void sub(FpT& z, const FpT& x, const FpT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_subA_(z.v_, x.v_, y.v_);
#else
op_.fp_sub(z.v_, x.v_, y.v_, op_.p);
#endif
}
static void neg(FpT& y, const FpT& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_negA_(y.v_, x.v_);
#else
op_.fp_neg(y.v_, x.v_, op_.p);
#endif
}
static void mul(FpT& z, const FpT& x, const FpT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_mulA_(z.v_, x.v_, y.v_);
#else
op_.fp_mul(z.v_, x.v_, y.v_, op_.p);
#endif
}
static void sqr(FpT& y, const FpT& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_sqrA_(y.v_, x.v_);
#else
op_.fp_sqr(y.v_, x.v_, op_.p);
#endif
}
static void mul2(FpT& y, const FpT& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
static void (*add)(FpT& z, const FpT& x, const FpT& y);
static inline void addC(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); }
static void (*sub)(FpT& z, const FpT& x, const FpT& y);
static inline void subC(FpT& z, const FpT& x, const FpT& y) { op_.fp_sub(z.v_, x.v_, y.v_, op_.p); }
static void (*neg)(FpT& y, const FpT& x);
static inline void negC(FpT& y, const FpT& x) { op_.fp_neg(y.v_, x.v_, op_.p); }
static void (*mul)(FpT& z, const FpT& x, const FpT& y);
static inline void mulC(FpT& z, const FpT& x, const FpT& y) { op_.fp_mul(z.v_, x.v_, y.v_, op_.p); }
static void (*sqr)(FpT& y, const FpT& x);
static inline void sqrC(FpT& y, const FpT& x) { op_.fp_sqr(y.v_, x.v_, op_.p); }
op_.fp_mul2A_(y.v_, x.v_);
#else
static inline void add(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); }
static inline void sub(FpT& z, const FpT& x, const FpT& y) { op_.fp_sub(z.v_, x.v_, y.v_, op_.p); }
static inline void neg(FpT& y, const FpT& x) { op_.fp_neg(y.v_, x.v_, op_.p); }
static inline void mul(FpT& z, const FpT& x, const FpT& y) { op_.fp_mul(z.v_, x.v_, y.v_, op_.p); }
static inline void sqr(FpT& y, const FpT& x) { op_.fp_sqr(y.v_, x.v_, op_.p); }
op_.fp_mul2(y.v_, x.v_, op_.p);
#endif
}
static void mul9(FpT& y, const FpT& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
op_.fp_mul9A_(y.v_, x.v_);
#else
mul9A(y.v_, x.v_);
#endif
}
static inline void addPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_addPre(z.v_, x.v_, y.v_); }
static inline void subPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_subPre(z.v_, x.v_, y.v_); }
static inline void mulSmall(FpT& z, const FpT& x, const uint32_t y)
{
mulSmall(z.v_, x.v_, y);
}
static inline void mulUnit(FpT& z, const FpT& x, const Unit y)
{
if (mulSmallUnit(z, x, y)) return;
op_.fp_mulUnit(z.v_, x.v_, y, op_.p);
}
static inline void inv(FpT& y, const FpT& x) { op_.fp_invOp(y.v_, x.v_, op_); }
static inline void inv(FpT& y, const FpT& x)
{
assert(!x.isZero());
op_.fp_invOp(y.v_, x.v_, op_);
}
static inline void divBy2(FpT& y, const FpT& x)
{
#if 0
@ -526,9 +730,12 @@ public:
}
static void setETHserialization(bool ETHserialization)
{
if (getBitSize() != 381) return;
isETHserialization_ = ETHserialization;
}
static bool getETHserialization()
{
return isETHserialization_;
}
static inline bool isETHserialization() { return isETHserialization_; }
static inline int getIoMode() { return ioMode_; }
static inline size_t getModBitLen() { return getBitSize(); }
@ -655,16 +862,10 @@ template<class tag, size_t maxBitSize> fp::Op FpT<tag, maxBitSize>::op_;
template<class tag, size_t maxBitSize> FpT<tag, maxBitSize> FpT<tag, maxBitSize>::inv2_;
template<class tag, size_t maxBitSize> int FpT<tag, maxBitSize>::ioMode_ = IoAuto;
template<class tag, size_t maxBitSize> bool FpT<tag, maxBitSize>::isETHserialization_ = false;
#ifdef MCL_XBYAK_DIRECT_CALL
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::add)(FpT& z, const FpT& x, const FpT& y);
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::sub)(FpT& z, const FpT& x, const FpT& y);
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::neg)(FpT& y, const FpT& x);
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::mul)(FpT& z, const FpT& x, const FpT& y);
template<class tag, size_t maxBitSize> void (*FpT<tag, maxBitSize>::sqr)(FpT& y, const FpT& x);
#endif
} // mcl
#ifndef CYBOZU_DONT_USE_EXCEPTION
#ifdef CYBOZU_USE_BOOST
namespace mcl {
@ -688,6 +889,7 @@ struct hash<mcl::FpT<tag, maxBitSize> > {
CYBOZU_NAMESPACE_TR1_END } // std::tr1
#endif
#endif
#ifdef _MSC_VER
#pragma warning(pop)

@ -10,22 +10,18 @@
namespace mcl {
template<class Fp> struct Fp12T;
template<class Fp> class BNT;
template<class Fp> struct Fp2DblT;
template<class Fp>
class FpDblT : public fp::Serializable<FpDblT<Fp> > {
typedef fp::Unit Unit;
Unit v_[Fp::maxSize * 2];
friend struct Fp2DblT<Fp>;
public:
static size_t getUnitSize() { return Fp::op_.N * 2; }
FpDblT() : v_()
{
}
FpDblT(const FpDblT& rhs)
{
const size_t n = getUnitSize();
for (size_t i = 0; i < n; i++) {
v_[i] = rhs.v_[i];
}
}
const fp::Unit *getUnit() const { return v_; }
void dump() const
{
const size_t n = getUnitSize();
@ -117,31 +113,42 @@ public:
{
gmp::setArray(pb, x, v_, Fp::op_.N * 2);
}
static inline void add(FpDblT& z, const FpDblT& x, const FpDblT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fpDbl_addA_(z.v_, x.v_, y.v_);
#else
Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p);
#endif
}
static inline void sub(FpDblT& z, const FpDblT& x, const FpDblT& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fpDbl_subA_(z.v_, x.v_, y.v_);
#else
Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p);
#endif
}
static inline void mod(Fp& z, const FpDblT& xy)
{
#ifdef MCL_XBYAK_DIRECT_CALL
static void (*add)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void (*sub)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void (*mod)(Fp& z, const FpDblT& xy);
static void (*addPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void (*subPre)(FpDblT& z, const FpDblT& x, const FpDblT& y);
static void addC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); }
static void subC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); }
static void modC(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); }
static void addPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); }
static void subPreC(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); }
Fp::op_.fpDbl_modA_(z.v_, xy.v_);
#else
static void add(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_add(z.v_, x.v_, y.v_, Fp::op_.p); }
static void sub(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_sub(z.v_, x.v_, y.v_, Fp::op_.p); }
static void mod(Fp& z, const FpDblT& xy) { Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p); }
Fp::op_.fpDbl_mod(z.v_, xy.v_, Fp::op_.p);
#endif
}
#ifdef MCL_XBYAK_DIRECT_CALL
static void addA(Unit *z, const Unit *x, const Unit *y) { Fp::op_.fpDbl_add(z, x, y, Fp::op_.p); }
static void subA(Unit *z, const Unit *x, const Unit *y) { Fp::op_.fpDbl_sub(z, x, y, Fp::op_.p); }
static void modA(Unit *z, const Unit *xy) { Fp::op_.fpDbl_mod(z, xy, Fp::op_.p); }
#endif
static void addPre(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_addPre(z.v_, x.v_, y.v_); }
static void subPre(FpDblT& z, const FpDblT& x, const FpDblT& y) { Fp::op_.fpDbl_subPre(z.v_, x.v_, y.v_); }
#endif
static void mulPreC(FpDblT& xy, const Fp& x, const Fp& y) { Fp::op_.fpDbl_mulPre(xy.v_, x.v_, y.v_); }
static void sqrPreC(FpDblT& xx, const Fp& x) { Fp::op_.fpDbl_sqrPre(xx.v_, x.v_); }
/*
mul(z, x, y) = mulPre(xy, x, y) + mod(z, xy)
*/
static void (*mulPre)(FpDblT& xy, const Fp& x, const Fp& y);
static void (*sqrPre)(FpDblT& xx, const Fp& x);
static void mulPre(FpDblT& xy, const Fp& x, const Fp& y) { Fp::op_.fpDbl_mulPre(xy.v_, x.v_, y.v_); }
static void sqrPre(FpDblT& xx, const Fp& x) { Fp::op_.fpDbl_sqrPre(xx.v_, x.v_); }
static void mulUnit(FpDblT& z, const FpDblT& x, Unit y)
{
if (mulSmallUnit(z, x, y)) return;
@ -149,47 +156,23 @@ public:
}
static void init()
{
const mcl::fp::Op& op = Fp::getOp();
#ifdef MCL_XBYAK_DIRECT_CALL
add = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_addA_);
if (add == 0) add = addC;
sub = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_subA_);
if (sub == 0) sub = subC;
mod = fp::func_ptr_cast<void (*)(Fp&, const FpDblT&)>(op.fpDbl_modA_);
if (mod == 0) mod = modC;
addPre = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_addPre);
if (addPre == 0) addPre = addPreC;
subPre = fp::func_ptr_cast<void (*)(FpDblT&, const FpDblT&, const FpDblT&)>(op.fpDbl_subPre);
if (subPre == 0) subPre = subPreC;
#endif
if (op.fpDbl_mulPreA_) {
mulPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&, const Fp&)>(op.fpDbl_mulPreA_);
} else {
mulPre = mulPreC;
mcl::fp::Op& op = Fp::op_;
if (op.fpDbl_addA_ == 0) {
op.fpDbl_addA_ = addA;
}
if (op.fpDbl_sqrPreA_) {
sqrPre = fp::func_ptr_cast<void (*)(FpDblT&, const Fp&)>(op.fpDbl_sqrPreA_);
} else {
sqrPre = sqrPreC;
if (op.fpDbl_subA_ == 0) {
op.fpDbl_subA_ = subA;
}
if (op.fpDbl_modA_ == 0) {
op.fpDbl_modA_ = modA;
}
#endif
}
void operator+=(const FpDblT& x) { add(*this, *this, x); }
void operator-=(const FpDblT& x) { sub(*this, *this, x); }
};
#ifdef MCL_XBYAK_DIRECT_CALL
template<class Fp> void (*FpDblT<Fp>::add)(FpDblT&, const FpDblT&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::sub)(FpDblT&, const FpDblT&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::mod)(Fp&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::addPre)(FpDblT&, const FpDblT&, const FpDblT&);
template<class Fp> void (*FpDblT<Fp>::subPre)(FpDblT&, const FpDblT&, const FpDblT&);
#endif
template<class Fp> void (*FpDblT<Fp>::mulPre)(FpDblT&, const Fp&, const Fp&);
template<class Fp> void (*FpDblT<Fp>::sqrPre)(FpDblT&, const Fp&);
template<class Fp> struct Fp12T;
template<class Fp> class BNT;
template<class Fp> struct Fp2DblT;
/*
beta = -1
Fp2 = F[i] / (i^2 + 1)
@ -240,22 +223,79 @@ public:
a = a_;
b = b_;
}
static void add(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_addA_(z.a.v_, x.a.v_, y.a.v_);
#else
addA(z.a.v_, x.a.v_, y.a.v_);
#endif
}
static void sub(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_subA_(z.a.v_, x.a.v_, y.a.v_);
#else
subA(z.a.v_, x.a.v_, y.a.v_);
#endif
}
static void neg(Fp2T& y, const Fp2T& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
static void (*add)(Fp2T& z, const Fp2T& x, const Fp2T& y);
static void (*sub)(Fp2T& z, const Fp2T& x, const Fp2T& y);
static void (*neg)(Fp2T& y, const Fp2T& x);
static void (*mul)(Fp2T& z, const Fp2T& x, const Fp2T& y);
static void (*sqr)(Fp2T& y, const Fp2T& x);
Fp::op_.fp2_negA_(y.a.v_, x.a.v_);
#else
static void add(Fp2T& z, const Fp2T& x, const Fp2T& y) { addC(z, x, y); }
static void sub(Fp2T& z, const Fp2T& x, const Fp2T& y) { subC(z, x, y); }
static void neg(Fp2T& y, const Fp2T& x) { negC(y, x); }
static void mul(Fp2T& z, const Fp2T& x, const Fp2T& y) { mulC(z, x, y); }
static void sqr(Fp2T& y, const Fp2T& x) { sqrC(y, x); }
negA(y.a.v_, x.a.v_);
#endif
static void (*mul_xi)(Fp2T& y, const Fp2T& x);
static void addPre(Fp2T& z, const Fp2T& x, const Fp2T& y) { Fp::addPre(z.a, x.a, y.a); Fp::addPre(z.b, x.b, y.b); }
static void inv(Fp2T& y, const Fp2T& x) { Fp::op_.fp2_inv(y.a.v_, x.a.v_); }
}
static void mul(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_mulA_(z.a.v_, x.a.v_, y.a.v_);
#else
mulA(z.a.v_, x.a.v_, y.a.v_);
#endif
}
static void sqr(Fp2T& y, const Fp2T& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_sqrA_(y.a.v_, x.a.v_);
#else
sqrA(y.a.v_, x.a.v_);
#endif
}
static void mul2(Fp2T& y, const Fp2T& x)
{
#ifdef MCL_XBYAK_DIRECT_CALL
Fp::op_.fp2_mul2A_(y.a.v_, x.a.v_);
#else
mul2A(y.a.v_, x.a.v_);
#endif
}
static void mul_xi(Fp2T& y, const Fp2T& x)
{
Fp::op_.fp2_mul_xiA_(y.a.v_, x.a.v_);
}
/*
x = a + bi
1 / x = (a - bi) / (a^2 + b^2)
*/
static void inv(Fp2T& y, const Fp2T& x)
{
assert(!x.isZero());
const Fp& a = x.a;
const Fp& b = x.b;
Fp r;
norm(r, x);
Fp::inv(r, r); // r = 1 / (a^2 + b^2)
Fp::mul(y.a, a, r);
Fp::mul(y.b, b, r);
Fp::neg(y.b, y.b);
}
static void addPre(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
Fp::addPre(z.a, x.a, y.a);
Fp::addPre(z.b, x.b, y.b);
}
static void divBy2(Fp2T& y, const Fp2T& x)
{
Fp::divBy2(y.a, x.a);
@ -360,12 +400,14 @@ public:
Fp::mul(y.b, x.b, t2);
return true;
}
// y = a^2 + b^2
static void inline norm(Fp& y, const Fp2T& x)
{
Fp aa, bb;
Fp::sqr(aa, x.a);
Fp::sqr(bb, x.b);
Fp::add(y, aa, bb);
FpDbl AA, BB;
FpDbl::sqrPre(AA, x.a);
FpDbl::sqrPre(BB, x.b);
FpDbl::addPre(AA, AA, BB);
FpDbl::mod(y, AA);
}
/*
Frobenius
@ -389,31 +431,40 @@ public:
}
static uint32_t get_xi_a() { return Fp::getOp().xi_a; }
static void init()
static void init(bool *pb)
{
// assert(Fp::maxSize <= 256);
mcl::fp::Op& op = Fp::op_;
assert(op.xi_a);
mul_xi = 0;
// assume p < W/4 where W = 1 << (N * sizeof(Unit) * 8)
if ((op.p[op.N - 1] >> (sizeof(fp::Unit) * 8 - 2)) != 0) {
*pb = false;
return;
}
#ifdef MCL_XBYAK_DIRECT_CALL
add = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_addA_);
if (add == 0) add = addC;
sub = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_subA_);
if (sub == 0) sub = subC;
neg = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_negA_);
if (neg == 0) neg = negC;
mul = fp::func_ptr_cast<void (*)(Fp2T& z, const Fp2T& x, const Fp2T& y)>(op.fp2_mulA_);
if (mul == 0) mul = mulC;
sqr = fp::func_ptr_cast<void (*)(Fp2T& y, const Fp2T& x)>(op.fp2_sqrA_);
if (sqr == 0) sqr = sqrC;
mul_xi = fp::func_ptr_cast<void (*)(Fp2T&, const Fp2T&)>(op.fp2_mul_xiA_);
if (op.fp2_addA_ == 0) {
op.fp2_addA_ = addA;
}
if (op.fp2_subA_ == 0) {
op.fp2_subA_ = subA;
}
if (op.fp2_negA_ == 0) {
op.fp2_negA_ = negA;
}
if (op.fp2_mulA_ == 0) {
op.fp2_mulA_ = mulA;
}
if (op.fp2_sqrA_ == 0) {
op.fp2_sqrA_ = sqrA;
}
if (op.fp2_mul2A_ == 0) {
op.fp2_mul2A_ = mul2A;
}
#endif
op.fp2_inv = fp2_invW;
if (mul_xi == 0) {
if (op.fp2_mul_xiA_ == 0) {
if (op.xi_a == 1) {
mul_xi = fp2_mul_xi_1_1iC;
op.fp2_mul_xiA_ = fp2_mul_xi_1_1iA;
} else {
mul_xi = fp2_mul_xiC;
op.fp2_mul_xiA_ = fp2_mul_xiA;
}
}
FpDblT<Fp>::init();
@ -446,8 +497,15 @@ public:
Fp2T::mul(g2[i], t, g[i]);
g3[i] = g[i] * g2[i];
}
*pb = true;
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
static void init()
{
bool b;
init(&b);
if (!b) throw cybozu::Exception("Fp2::init");
}
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
@ -484,75 +542,65 @@ public:
}
#endif
private:
static Fp2T& cast(Unit *x) { return *reinterpret_cast<Fp2T*>(x); }
static const Fp2T& cast(const Unit *x) { return *reinterpret_cast<const Fp2T*>(x); }
/*
default Fp2T operator
Fp2T = Fp[i]/(i^2 + 1)
*/
static void addC(Fp2T& z, const Fp2T& x, const Fp2T& y)
static void addA(Unit *pz, const Unit *px, const Unit *py)
{
Fp2T& z = cast(pz);
const Fp2T& x = cast(px);
const Fp2T& y = cast(py);
Fp::add(z.a, x.a, y.a);
Fp::add(z.b, x.b, y.b);
}
static void subC(Fp2T& z, const Fp2T& x, const Fp2T& y)
static void subA(Unit *pz, const Unit *px, const Unit *py)
{
Fp2T& z = cast(pz);
const Fp2T& x = cast(px);
const Fp2T& y = cast(py);
Fp::sub(z.a, x.a, y.a);
Fp::sub(z.b, x.b, y.b);
}
static void negC(Fp2T& y, const Fp2T& x)
static void negA(Unit *py, const Unit *px)
{
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
Fp::neg(y.a, x.a);
Fp::neg(y.b, x.b);
}
#if 0
/*
x = a + bi, y = c + di, i^2 = -1
z = xy = (a + bi)(c + di) = (ac - bd) + (ad + bc)i
ad+bc = (a + b)(c + d) - ac - bd
# of mod = 3
*/
static void fp2_mulW(Unit *z, const Unit *x, const Unit *y)
{
const Fp *px = reinterpret_cast<const Fp*>(x);
const Fp *py = reinterpret_cast<const Fp*>(y);
const Fp& a = px[0];
const Fp& b = px[1];
const Fp& c = py[0];
const Fp& d = py[1];
Fp *pz = reinterpret_cast<Fp*>(z);
Fp t1, t2, ac, bd;
Fp::add(t1, a, b);
Fp::add(t2, c, d);
t1 *= t2; // (a + b)(c + d)
Fp::mul(ac, a, c);
Fp::mul(bd, b, d);
Fp::sub(pz[0], ac, bd); // ac - bd
Fp::sub(pz[1], t1, ac);
pz[1] -= bd;
}
static void fp2_mulNFW(Fp2T& z, const Fp2T& x, const Fp2T& y)
{
const fp::Op& op = Fp::op_;
op.fp2_mulNF((Unit*)&z, (const Unit*)&x, (const Unit*)&y, op.p);
}
#endif
static void mulC(Fp2T& z, const Fp2T& x, const Fp2T& y)
static void mulA(Unit *pz, const Unit *px, const Unit *py)
{
Fp2T& z = cast(pz);
const Fp2T& x = cast(px);
const Fp2T& y = cast(py);
Fp2Dbl d;
Fp2Dbl::mulPre(d, x, y);
FpDbl::mod(z.a, d.a);
FpDbl::mod(z.b, d.b);
}
static void mul2A(Unit *py, const Unit *px)
{
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
Fp::mul2(y.a, x.a);
Fp::mul2(y.b, x.b);
}
/*
x = a + bi, i^2 = -1
y = x^2 = (a + bi)^2 = (a + b)(a - b) + 2abi
*/
static void sqrC(Fp2T& y, const Fp2T& x)
static void sqrA(Unit *py, const Unit *px)
{
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
const Fp& a = x.a;
const Fp& b = x.b;
#if 1 // faster than using FpDbl
Fp t1, t2, t3;
Fp::add(t1, b, b); // 2b
Fp::mul2(t1, b);
t1 *= a; // 2ab
Fp::add(t2, a, b); // a + b
Fp::sub(t3, a, b); // a - b
@ -576,8 +624,10 @@ private:
y = (a + bi)xi = (a + bi)(xi_a + i)
=(a * x_ia - b) + (a + b xi_a)i
*/
static void fp2_mul_xiC(Fp2T& y, const Fp2T& x)
static void fp2_mul_xiA(Unit *py, const Unit *px)
{
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
const Fp& a = x.a;
const Fp& b = x.b;
Fp t;
@ -591,8 +641,10 @@ private:
xi = 1 + i ; xi_a = 1
y = (a + bi)xi = (a - b) + (a + b)i
*/
static void fp2_mul_xi_1_1iC(Fp2T& y, const Fp2T& x)
static void fp2_mul_xi_1_1iA(Unit *py, const Unit *px)
{
Fp2T& y = cast(py);
const Fp2T& x = cast(px);
const Fp& a = x.a;
const Fp& b = x.b;
Fp t;
@ -600,38 +652,11 @@ private:
Fp::sub(y.a, a, b);
y.b = t;
}
/*
x = a + bi
1 / x = (a - bi) / (a^2 + b^2)
*/
static void fp2_invW(Unit *y, const Unit *x)
{
const Fp *px = reinterpret_cast<const Fp*>(x);
Fp *py = reinterpret_cast<Fp*>(y);
const Fp& a = px[0];
const Fp& b = px[1];
Fp aa, bb;
Fp::sqr(aa, a);
Fp::sqr(bb, b);
aa += bb;
Fp::inv(aa, aa); // aa = 1 / (a^2 + b^2)
Fp::mul(py[0], a, aa);
Fp::mul(py[1], b, aa);
Fp::neg(py[1], py[1]);
}
};
#ifdef MCL_XBYAK_DIRECT_CALL
template<class Fp_> void (*Fp2T<Fp_>::add)(Fp2T& z, const Fp2T& x, const Fp2T& y);
template<class Fp_> void (*Fp2T<Fp_>::sub)(Fp2T& z, const Fp2T& x, const Fp2T& y);
template<class Fp_> void (*Fp2T<Fp_>::neg)(Fp2T& y, const Fp2T& x);
template<class Fp_> void (*Fp2T<Fp_>::mul)(Fp2T& z, const Fp2T& x, const Fp2T& y);
template<class Fp_> void (*Fp2T<Fp_>::sqr)(Fp2T& y, const Fp2T& x);
#endif
template<class Fp_> void (*Fp2T<Fp_>::mul_xi)(Fp2T& y, const Fp2T& x);
template<class Fp>
struct Fp2DblT {
typedef Fp2DblT<Fp> Fp2Dbl;
typedef FpDblT<Fp> FpDbl;
typedef Fp2T<Fp> Fp2;
typedef fp::Unit Unit;
@ -656,30 +681,32 @@ struct Fp2DblT {
FpDbl::subPre(z.a, x.a, y.a);
FpDbl::subPre(z.b, x.b, y.b);
}
/*
imaginary part of Fp2Dbl::mul uses only add,
so it does not require mod.
*/
static void subSpecial(Fp2DblT& y, const Fp2DblT& x)
{
FpDbl::sub(y.a, y.a, x.a);
FpDbl::subPre(y.b, y.b, x.b);
}
static void neg(Fp2DblT& y, const Fp2DblT& x)
{
FpDbl::neg(y.a, x.a);
FpDbl::neg(y.b, x.b);
}
static void mulPre(Fp2DblT& z, const Fp2& x, const Fp2& y)
{
Fp::getOp().fp2Dbl_mulPreA_(z.a.v_, x.getUnit(), y.getUnit());
}
static void sqrPre(Fp2DblT& y, const Fp2& x)
{
Fp::getOp().fp2Dbl_sqrPreA_(y.a.v_, x.getUnit());
}
static void mul_xi(Fp2DblT& y, const Fp2DblT& x)
{
const uint32_t xi_a = Fp2::get_xi_a();
if (xi_a == 1) {
FpDbl t;
FpDbl::add(t, x.a, x.b);
FpDbl::sub(y.a, x.a, x.b);
y.b = t;
} else {
FpDbl t;
FpDbl::mulUnit(t, x.a, xi_a);
FpDbl::sub(t, t, x.b);
FpDbl::mulUnit(y.b, x.b, xi_a);
FpDbl::add(y.b, y.b, x.a);
y.a = t;
}
Fp::getOp().fp2Dbl_mul_xiA_(y.a.v_, x.a.getUnit());
}
static void (*mulPre)(Fp2DblT&, const Fp2&, const Fp2&);
static void (*sqrPre)(Fp2DblT&, const Fp2&);
static void mod(Fp2& y, const Fp2DblT& x)
{
FpDbl::mod(y.a, x.a);
@ -695,33 +722,38 @@ struct Fp2DblT {
void operator-=(const Fp2DblT& x) { sub(*this, *this, x); }
static void init()
{
const mcl::fp::Op& op = Fp::getOp();
if (op.fp2Dbl_mulPreA_) {
mulPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&, const Fp2&)>(op.fp2Dbl_mulPreA_);
} else {
if (op.isFullBit) {
mulPre = fp2Dbl_mulPreW<true>;
} else {
mulPre = fp2Dbl_mulPreW<false>;
}
assert(!Fp::getOp().isFullBit);
mcl::fp::Op& op = Fp::getOpNonConst();
if (op.fp2Dbl_mulPreA_ == 0) {
op.fp2Dbl_mulPreA_ = mulPreA;
}
if (op.fp2Dbl_sqrPreA_) {
sqrPre = fp::func_ptr_cast<void (*)(Fp2DblT&, const Fp2&)>(op.fp2Dbl_sqrPreA_);
} else {
if (op.isFullBit) {
sqrPre = fp2Dbl_sqrPreW<true>;
if (op.fp2Dbl_sqrPreA_ == 0) {
op.fp2Dbl_sqrPreA_ = sqrPreA;
}
if (op.fp2Dbl_mul_xiA_ == 0) {
const uint32_t xi_a = Fp2::get_xi_a();
if (xi_a == 1) {
op.fp2Dbl_mul_xiA_ = mul_xi_1A;
} else {
sqrPre = fp2Dbl_sqrPreW<false>;
op.fp2Dbl_mul_xiA_ = mul_xi_genericA;
}
}
}
private:
static Fp2 cast(Unit *x) { return *reinterpret_cast<Fp2*>(x); }
static const Fp2 cast(const Unit *x) { return *reinterpret_cast<const Fp2*>(x); }
static Fp2Dbl& castD(Unit *x) { return *reinterpret_cast<Fp2Dbl*>(x); }
static const Fp2Dbl& castD(const Unit *x) { return *reinterpret_cast<const Fp2Dbl*>(x); }
/*
Fp2Dbl::mulPre by FpDblT
@note mod of NIST_P192 is fast
*/
template<bool isFullBit>
static void fp2Dbl_mulPreW(Fp2DblT& z, const Fp2& x, const Fp2& y)
static void mulPreA(Unit *pz, const Unit *px, const Unit *py)
{
Fp2Dbl& z = castD(pz);
const Fp2& x = cast(px);
const Fp2& y = cast(py);
assert(!Fp::getOp().isFullBit);
const Fp& a = x.a;
const Fp& b = x.b;
const Fp& c = y.a;
@ -730,45 +762,50 @@ struct Fp2DblT {
FpDbl& d1 = z.b;
FpDbl d2;
Fp s, t;
if (isFullBit) {
Fp::add(s, a, b);
Fp::add(t, c, d);
} else {
Fp::addPre(s, a, b);
Fp::addPre(t, c, d);
}
Fp::addPre(s, a, b);
Fp::addPre(t, c, d);
FpDbl::mulPre(d1, s, t); // (a + b)(c + d)
FpDbl::mulPre(d0, a, c);
FpDbl::mulPre(d2, b, d);
if (isFullBit) {
FpDbl::sub(d1, d1, d0); // (a + b)(c + d) - ac
FpDbl::sub(d1, d1, d2); // (a + b)(c + d) - ac - bd
} else {
FpDbl::subPre(d1, d1, d0);
FpDbl::subPre(d1, d1, d2);
}
FpDbl::subPre(d1, d1, d0);
FpDbl::subPre(d1, d1, d2);
FpDbl::sub(d0, d0, d2); // ac - bd
}
template<bool isFullBit>
static void fp2Dbl_sqrPreW(Fp2DblT& y, const Fp2& x)
static void sqrPreA(Unit *py, const Unit *px)
{
assert(!Fp::getOp().isFullBit);
Fp2Dbl& y = castD(py);
const Fp2& x = cast(px);
Fp t1, t2;
if (isFullBit) {
Fp::add(t1, x.b, x.b); // 2b
Fp::add(t2, x.a, x.b); // a + b
} else {
Fp::addPre(t1, x.b, x.b); // 2b
Fp::addPre(t2, x.a, x.b); // a + b
}
Fp::addPre(t1, x.b, x.b); // 2b
Fp::addPre(t2, x.a, x.b); // a + b
FpDbl::mulPre(y.b, t1, x.a); // 2ab
Fp::sub(t1, x.a, x.b); // a - b
FpDbl::mulPre(y.a, t1, t2); // (a + b)(a - b)
}
static void mul_xi_1A(Unit *py, const Unit *px)
{
Fp2Dbl& y = castD(py);
const Fp2Dbl& x = castD(px);
FpDbl t;
FpDbl::add(t, x.a, x.b);
FpDbl::sub(y.a, x.a, x.b);
y.b = t;
}
static void mul_xi_genericA(Unit *py, const Unit *px)
{
const uint32_t xi_a = Fp2::get_xi_a();
Fp2Dbl& y = castD(py);
const Fp2Dbl& x = castD(px);
FpDbl t;
FpDbl::mulUnit(t, x.a, xi_a);
FpDbl::sub(t, t, x.b);
FpDbl::mulUnit(y.b, x.b, xi_a);
FpDbl::add(y.b, y.b, x.a);
y.a = t;
}
};
template<class Fp> void (*Fp2DblT<Fp>::mulPre)(Fp2DblT&, const Fp2T<Fp>&, const Fp2T<Fp>&);
template<class Fp> void (*Fp2DblT<Fp>::sqrPre)(Fp2DblT&, const Fp2T<Fp>&);
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g[Fp2T<Fp>::gN];
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g2[Fp2T<Fp>::gN];
template<class Fp> Fp2T<Fp> Fp2T<Fp>::g3[Fp2T<Fp>::gN];
@ -889,34 +926,24 @@ struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
Fp2::neg(y.b, x.b);
Fp2::neg(y.c, x.c);
}
/*
x = a + bv + cv^2, v^3 = xi
x^2 = (a^2 + 2bc xi) + (c^2 xi + 2ab)v + (b^2 + 2ac)v^2
b^2 + 2ac = (a + b + c)^2 - a^2 - 2bc - c^2 - 2ab
*/
static void mul2(Fp6T& y, const Fp6T& x)
{
Fp2::mul2(y.a, x.a);
Fp2::mul2(y.b, x.b);
Fp2::mul2(y.c, x.c);
}
static void sqr(Fp6T& y, const Fp6T& x)
{
Fp2 t1, t2, t3;
Fp2::mul(t1, x.a, x.b);
t1 += t1; // 2ab
Fp2::mul(t2, x.b, x.c);
t2 += t2; // 2bc
Fp2::sqr(t3, x.c); // c^2
Fp2::add(y.c, x.a, x.c); // a + c, destroy y.c
y.c += x.b; // a + b + c
Fp2::sqr(y.b, y.c); // (a + b + c)^2, destroy y.b
y.b -= t2; // (a + b + c)^2 - 2bc
Fp2::mul_xi(t2, t2); // 2bc xi
Fp2::sqr(y.a, x.a); // a^2, destroy y.a
y.b -= y.a; // (a + b + c)^2 - 2bc - a^2
y.a += t2; // a^2 + 2bc xi
Fp2::sub(y.c, y.b, t3); // (a + b + c)^2 - 2bc - a^2 - c^2
Fp2::mul_xi(y.b, t3); // c^2 xi
y.b += t1; // c^2 xi + 2ab
y.c -= t1; // b^2 + 2ac
}
static inline void mul(Fp6T& z, const Fp6T& x, const Fp6T& y);
Fp6Dbl XX;
Fp6Dbl::sqrPre(XX, x);
Fp6Dbl::mod(y, XX);
}
static inline void mul(Fp6T& z, const Fp6T& x, const Fp6T& y)
{
Fp6Dbl XY;
Fp6Dbl::mulPre(XY, x, y);
Fp6Dbl::mod(z, XY);
}
/*
x = a + bv + cv^2, v^3 = xi
y = 1/x = p/q where
@ -929,27 +956,34 @@ struct Fp6T : public fp::Serializable<Fp6T<_Fp>,
const Fp2& a = x.a;
const Fp2& b = x.b;
const Fp2& c = x.c;
Fp2 aa, bb, cc, ab, bc, ac;
Fp2::sqr(aa, a);
Fp2::sqr(bb, b);
Fp2::sqr(cc, c);
Fp2::mul(ab, a, b);
Fp2::mul(bc, b, c);
Fp2::mul(ac, c, a);
Fp2Dbl aa, bb, cc, ab, bc, ac;
Fp2Dbl::sqrPre(aa, a);
Fp2Dbl::sqrPre(bb, b);
Fp2Dbl::sqrPre(cc, c);
Fp2Dbl::mulPre(ab, a, b);
Fp2Dbl::mulPre(bc, b, c);
Fp2Dbl::mulPre(ac, c, a);
Fp6T p;
Fp2::mul_xi(p.a, bc);
Fp2::sub(p.a, aa, p.a); // a^2 - bc xi
Fp2::mul_xi(p.b, cc);
p.b -= ab; // c^2 xi - ab
Fp2::sub(p.c, bb, ac); // b^2 - ac
Fp2 q, t;
Fp2::mul(q, p.b, c);
Fp2::mul(t, p.c, b);
q += t;
Fp2::mul_xi(q, q);
Fp2::mul(t, p.a, a);
q += t;
Fp2Dbl T;
Fp2Dbl::mul_xi(T, bc);
Fp2Dbl::sub(T, aa, T); // a^2 - bc xi
Fp2Dbl::mod(p.a, T);
Fp2Dbl::mul_xi(T, cc);
Fp2Dbl::sub(T, T, ab); // c^2 xi - ab
Fp2Dbl::mod(p.b, T);
Fp2Dbl::sub(T, bb, ac); // b^2 - ac
Fp2Dbl::mod(p.c, T);
Fp2Dbl T2;
Fp2Dbl::mulPre(T, p.b, c);
Fp2Dbl::mulPre(T2, p.c, b);
Fp2Dbl::add(T, T, T2);
Fp2Dbl::mul_xi(T, T);
Fp2Dbl::mulPre(T2, p.a, a);
Fp2Dbl::addPre(T, T, T2);
Fp2 q;
Fp2Dbl::mod(q, T);
Fp2::inv(q, q);
Fp2::mul(y.a, p.a, q);
@ -962,6 +996,7 @@ template<class Fp>
struct Fp6DblT {
typedef Fp2T<Fp> Fp2;
typedef Fp6T<Fp> Fp6;
typedef FpDblT<Fp> FpDbl;
typedef Fp2DblT<Fp> Fp2Dbl;
typedef Fp6DblT<Fp> Fp6Dbl;
typedef fp::Unit Unit;
@ -984,51 +1019,75 @@ struct Fp6DblT {
bf + ce = (b + c)(e + f) - be - cf
ae + bd = (a + b)(e + d) - ad - be
af + cd = (a + c)(d + f) - ad - cf
assum p < W/4 where W = 1 << (sizeof(Unit) * 8 * N)
then (b + c)(e + f) < 4p^2 < pW
*/
static void mulPre(Fp6DblT& z, const Fp6& x, const Fp6& y)
{
//clk.begin();
const Fp2& a = x.a;
const Fp2& b = x.b;
const Fp2& c = x.c;
const Fp2& d = y.a;
const Fp2& e = y.b;
const Fp2& f = y.c;
Fp2Dbl& za = z.a;
Fp2Dbl& zb = z.b;
Fp2Dbl& zc = z.c;
Fp2Dbl BE;
Fp2Dbl::mulPre(za, a, d);
Fp2Dbl& ZA = z.a;
Fp2Dbl& ZB = z.b;
Fp2Dbl& ZC = z.c;
Fp2 t1, t2;
Fp2Dbl BE, CF, AD;
Fp2::addPre(t1, b, c);
Fp2::addPre(t2, e, f);
Fp2Dbl::mulPre(ZA, t1, t2);
Fp2::addPre(t1, a, b);
Fp2::addPre(t2, e, d);
Fp2Dbl::mulPre(ZB, t1, t2);
Fp2::addPre(t1, a, c);
Fp2::addPre(t2, d, f);
Fp2Dbl::mulPre(ZC, t1, t2);
Fp2Dbl::mulPre(BE, b, e);
Fp2Dbl::mulPre(zb, c, f);
Fp2 t1, t2, t3, t4;
Fp2::add(t1, b, c);
Fp2::add(t2, e, f);
Fp2Dbl T1;
Fp2Dbl::mulPre(T1, t1, t2);
Fp2Dbl::sub(T1, T1, BE);
Fp2Dbl::sub(T1, T1, zb);
Fp2Dbl::mul_xi(T1, T1);
Fp2::add(t2, a, b);
Fp2::add(t3, e, d);
Fp2Dbl T2;
Fp2Dbl::mulPre(T2, t2, t3);
Fp2Dbl::sub(T2, T2, za);
Fp2Dbl::sub(T2, T2, BE);
Fp2::add(t3, a, c);
Fp2::add(t4, d, f);
Fp2Dbl::mulPre(zc, t3, t4);
Fp2Dbl::sub(zc, zc, za);
Fp2Dbl::sub(zc, zc, zb);
Fp2Dbl::mulPre(CF, c, f);
Fp2Dbl::mulPre(AD, a, d);
Fp2Dbl::subSpecial(ZA, BE);
Fp2Dbl::subSpecial(ZA, CF);
Fp2Dbl::subSpecial(ZB, AD);
Fp2Dbl::subSpecial(ZB, BE);
Fp2Dbl::subSpecial(ZC, AD);
Fp2Dbl::subSpecial(ZC, CF);
Fp2Dbl::mul_xi(ZA, ZA);
Fp2Dbl::add(ZA, ZA, AD);
Fp2Dbl::mul_xi(CF, CF);
Fp2Dbl::add(ZB, ZB, CF);
Fp2Dbl::add(ZC, ZC, BE);
}
/*
x = a + bv + cv^2, v^3 = xi
x^2 = (a^2 + 2bc xi) + (c^2 xi + 2ab)v + (b^2 + 2ac)v^2
Fp2Dbl::add(za, za, T1);
Fp2Dbl::mul_xi(zb, zb);
Fp2Dbl::add(zb, zb, T2);
Fp2Dbl::add(zc, zc, BE);
//clk.end();
b^2 + 2ac = (a + b + c)^2 - a^2 - 2bc - c^2 - 2ab
*/
static void sqrPre(Fp6DblT& y, const Fp6& x)
{
const Fp2& a = x.a;
const Fp2& b = x.b;
const Fp2& c = x.c;
Fp2 t;
Fp2Dbl BC2, AB2, AA, CC, T;
Fp2::mul2(t, b);
Fp2Dbl::mulPre(BC2, t, c); // 2bc
Fp2Dbl::mulPre(AB2, t, a); // 2ab
Fp2Dbl::sqrPre(AA, a);
Fp2Dbl::sqrPre(CC, c);
Fp2::add(t, a, b);
Fp2::add(t, t, c);
Fp2Dbl::sqrPre(T, t); // (a + b + c)^2
Fp2Dbl::sub(T, T, AA);
Fp2Dbl::sub(T, T, BC2);
Fp2Dbl::sub(T, T, CC);
Fp2Dbl::sub(y.c, T, AB2);
Fp2Dbl::mul_xi(BC2, BC2);
Fp2Dbl::add(y.a, AA, BC2);
Fp2Dbl::mul_xi(CC, CC);
Fp2Dbl::add(y.b, CC, AB2);
}
static void mod(Fp6& y, const Fp6Dbl& x)
{
@ -1038,14 +1097,6 @@ struct Fp6DblT {
}
};
template<class Fp>
inline void Fp6T<Fp>::mul(Fp6T<Fp>& z, const Fp6T<Fp>& x, const Fp6T<Fp>& y)
{
Fp6DblT<Fp> Z;
Fp6DblT<Fp>::mulPre(Z, x, y);
Fp6DblT<Fp>::mod(z, Z);
}
/*
Fp12T = Fp6[w] / (w^2 - v)
x = a + b w
@ -1148,7 +1199,6 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
Fp6 t1, t2;
Fp6::add(t1, a, b);
Fp6::add(t2, c, d);
#if 1
Fp6Dbl T, AC, BD;
Fp6Dbl::mulPre(AC, a, c);
Fp6Dbl::mulPre(BD, b, d);
@ -1158,15 +1208,6 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
Fp6Dbl::sub(T, T, AC);
Fp6Dbl::sub(T, T, BD);
Fp6Dbl::mod(z.b, T);
#else
Fp6 ac, bd;
t1 *= t2; // (a + b)(c + d)
Fp6::mul(ac, a, c);
Fp6::mul(bd, b, d);
mulVadd(z.a, bd, ac);
t1 -= ac;
Fp6::sub(z.b, t1, bd);
#endif
}
/*
x = a + bw, w^2 = v
@ -1182,7 +1223,7 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
mulVadd(t1, b, a); // bv + a
t0 *= t1; // (a + b)(bv + a)
Fp6::mul(t1, a, b); // ab
Fp6::add(y.b, t1, t1); // 2ab
Fp6::mul2(y.b, t1); // 2ab
mulVadd(y.a, t1, t1); // abv + ab
Fp6::sub(y.a, t0, y.a);
}
@ -1194,16 +1235,18 @@ struct Fp12T : public fp::Serializable<Fp12T<Fp>,
{
const Fp6& a = x.a;
const Fp6& b = x.b;
Fp6 t0, t1;
Fp6::sqr(t0, a);
Fp6::sqr(t1, b);
Fp2::mul_xi(t1.c, t1.c);
t0.a -= t1.c;
t0.b -= t1.a;
t0.c -= t1.b; // t0 = a^2 - b^2v
Fp6::inv(t0, t0);
Fp6::mul(y.a, x.a, t0);
Fp6::mul(y.b, x.b, t0);
Fp6Dbl AA, BB;
Fp6Dbl::sqrPre(AA, a);
Fp6Dbl::sqrPre(BB, b);
Fp2Dbl::mul_xi(BB.c, BB.c);
Fp2Dbl::sub(AA.a, AA.a, BB.c);
Fp2Dbl::sub(AA.b, AA.b, BB.a);
Fp2Dbl::sub(AA.c, AA.c, BB.b); // a^2 - b^2 v
Fp6 t;
Fp6Dbl::mod(t, AA);
Fp6::inv(t, t);
Fp6::mul(y.a, x.a, t);
Fp6::mul(y.b, x.b, t);
Fp6::neg(y.b, y.b);
}
/*
@ -1336,6 +1379,12 @@ struct GroupMtoA : public T {
{
T::mul(castT(z), castT(x), castT(y));
}
static void sub(GroupMtoA& z, const GroupMtoA& x, const GroupMtoA& y)
{
T r;
T::unitaryInv(r, castT(y));
T::mul(castT(z), castT(x), r);
}
static void dbl(GroupMtoA& y, const GroupMtoA& x)
{
T::sqr(castT(y), castT(x));
@ -1363,6 +1412,10 @@ struct GroupMtoA : public T {
{
add(*this, *this, rhs);
}
void operator-=(const GroupMtoA& rhs)
{
sub(*this, *this, rhs);
}
void normalize() {}
private:
bool isOne() const;

@ -10,10 +10,14 @@
#include <stdlib.h>
#include <assert.h>
#include <stdint.h>
#include <cybozu/bit_operation.hpp>
#ifndef CYBOZU_DONT_USE_EXCEPTION
#include <cybozu/exception.hpp>
#endif
#include <mcl/randgen.hpp>
#include <mcl/config.hpp>
#include <mcl/conversion.hpp>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4616)
@ -26,9 +30,6 @@
#if defined(__EMSCRIPTEN__) || defined(__wasm__)
#define MCL_USE_VINT
#endif
#ifndef MCL_MAX_BIT_SIZE
#define MCL_MAX_BIT_SIZE 521
#endif
#ifdef MCL_USE_VINT
#include <mcl/vint.hpp>
typedef mcl::Vint mpz_class;
@ -40,27 +41,8 @@ typedef mcl::Vint mpz_class;
#endif
#endif
#ifndef MCL_SIZEOF_UNIT
#if defined(CYBOZU_OS_BIT) && (CYBOZU_OS_BIT == 32)
#define MCL_SIZEOF_UNIT 4
#else
#define MCL_SIZEOF_UNIT 8
#endif
#endif
namespace mcl {
namespace fp {
#if MCL_SIZEOF_UNIT == 8
typedef uint64_t Unit;
#else
typedef uint32_t Unit;
#endif
#define MCL_UNIT_BIT_SIZE (MCL_SIZEOF_UNIT * 8)
} // mcl::fp
namespace gmp {
typedef mpz_class ImplType;
@ -81,24 +63,20 @@ void setArray(bool *pb, mpz_class& z, const T *buf, size_t n)
buf[0, size) = x
buf[size, maxSize) with zero
*/
template<class T, class U>
bool getArray_(T *buf, size_t maxSize, const U *x, int xn)//const mpz_srcptr x)
{
const size_t bufByteSize = sizeof(T) * maxSize;
if (xn < 0) return false;
size_t xByteSize = sizeof(*x) * xn;
if (xByteSize > bufByteSize) return false;
memcpy(buf, x, xByteSize);
memset((char*)buf + xByteSize, 0, bufByteSize - xByteSize);
return true;
}
template<class T>
void getArray(bool *pb, T *buf, size_t maxSize, const mpz_class& x)
{
#ifdef MCL_USE_VINT
*pb = getArray_(buf, maxSize, x.getUnit(), x.getUnitSize());
const fp::Unit *src = x.getUnit();
const size_t n = x.getUnitSize();
*pb = fp::convertArrayAsLE(buf, maxSize, src, n);
#else
*pb = getArray_(buf, maxSize, x.get_mpz_t()->_mp_d, x.get_mpz_t()->_mp_size);
int n = x.get_mpz_t()->_mp_size;
if (n < 0) {
*pb = false;
return;
}
*pb = fp::convertArrayAsLE(buf, maxSize, x.get_mpz_t()->_mp_d, n);
#endif
}
inline void set(mpz_class& z, uint64_t x)
@ -434,6 +412,36 @@ inline size_t getUnitSize(const mpz_class& x)
return std::abs(x.get_mpz_t()->_mp_size);
#endif
}
/*
get the number of lower zeros
*/
template<class T>
size_t getLowerZeroBitNum(const T *x, size_t n)
{
size_t ret = 0;
for (size_t i = 0; i < n; i++) {
T v = x[i];
if (v == 0) {
ret += sizeof(T) * 8;
} else {
ret += cybozu::bsf<T>(v);
break;
}
}
return ret;
}
/*
get the number of lower zero
@note x != 0
*/
inline size_t getLowerZeroBitNum(const mpz_class& x)
{
assert(!isZero(x));
return getLowerZeroBitNum(getUnit(x), getUnitSize(x));
}
inline mpz_class abs(const mpz_class& x)
{
#ifdef MCL_USE_VINT
@ -576,6 +584,53 @@ bool getNAF(Vec& v, const mpz_class& x)
}
}
/*
v = naf[i]
v = 0 or (|v| <= 2^(w-1) - 1 and odd)
*/
template<class Vec>
void getNAFwidth(bool *pb, Vec& naf, mpz_class x, size_t w)
{
assert(w > 0);
*pb = true;
naf.clear();
bool negative = false;
if (x < 0) {
negative = true;
x = -x;
}
size_t zeroNum = 0;
const int signedMaxW = 1 << (w - 1);
const int maxW = signedMaxW * 2;
const int maskW = maxW - 1;
while (!isZero(x)) {
size_t z = gmp::getLowerZeroBitNum(x);
if (z) {
x >>= z;
zeroNum += z;
}
for (size_t i = 0; i < zeroNum; i++) {
naf.push(pb, 0);
if (!*pb) return;
}
assert(!isZero(x));
int v = getUnit(x)[0] & maskW;
x >>= w;
if (v & signedMaxW) {
x++;
v -= maxW;
}
naf.push(pb, typename Vec::value_type(v));
if (!*pb) return;
zeroNum = w - 1;
}
if (negative) {
for (size_t i = 0; i < naf.size(); i++) {
naf[i] = -naf[i];
}
}
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
inline void setStr(mpz_class& z, const std::string& str, int base = 0)
{
@ -864,6 +919,86 @@ public:
#endif
};
/*
x mod p for a small value x < (pMulTblN * p).
*/
struct SmallModp {
typedef mcl::fp::Unit Unit;
static const size_t unitBitSize = sizeof(Unit) * 8;
static const size_t maxTblSize = (MCL_MAX_BIT_SIZE + unitBitSize - 1) / unitBitSize + 1;
static const size_t maxMulN = 9;
static const size_t pMulTblN = maxMulN + 1;
uint32_t N_;
uint32_t shiftL_;
uint32_t shiftR_;
uint32_t maxIdx_;
// pMulTbl_[i] = (p * i) >> (pBitSize_ - 1)
Unit pMulTbl_[pMulTblN][maxTblSize];
// idxTbl_[x] = (x << (pBitSize_ - 1)) / p
uint8_t idxTbl_[pMulTblN * 2];
// return x >> (pBitSize_ - 1)
SmallModp()
: N_(0)
, shiftL_(0)
, shiftR_(0)
, maxIdx_(0)
, pMulTbl_()
, idxTbl_()
{
}
// return argmax { i : x > i * p }
uint32_t approxMul(const Unit *x) const
{
uint32_t top = getTop(x);
assert(top <= maxIdx_);
return idxTbl_[top];
}
const Unit *getPmul(size_t v) const
{
assert(v < pMulTblN);
return pMulTbl_[v];
}
uint32_t getTop(const Unit *x) const
{
if (shiftR_ == 0) return x[N_ - 1];
return (x[N_ - 1] >> shiftR_) | (x[N_] << shiftL_);
}
uint32_t cvtInt(const mpz_class& x) const
{
assert(mcl::gmp::getUnitSize(x) <= 1);
if (x == 0) {
return 0;
} else {
return uint32_t(mcl::gmp::getUnit(x)[0]);
}
}
void init(const mpz_class& p)
{
size_t pBitSize = mcl::gmp::getBitSize(p);
N_ = uint32_t((pBitSize + unitBitSize - 1) / unitBitSize);
shiftR_ = (pBitSize - 1) % unitBitSize;
shiftL_ = unitBitSize - shiftR_;
mpz_class t = 0;
for (size_t i = 0; i < pMulTblN; i++) {
bool b;
mcl::gmp::getArray(&b, pMulTbl_[i], maxTblSize, t);
assert(b);
(void)b;
if (i == pMulTblN - 1) {
maxIdx_ = getTop(pMulTbl_[i]);
assert(maxIdx_ < CYBOZU_NUM_OF_ARRAY(idxTbl_));
break;
}
t += p;
}
for (uint32_t i = 0; i <= maxIdx_; i++) {
idxTbl_[i] = cvtInt((mpz_class(int(i)) << (pBitSize - 1)) / p);
}
}
};
/*
Barrett Reduction
for non GMP version

@ -77,12 +77,18 @@ int mclBn_init(int curve, int compiledTimeVar)
initG1only(&b, *para);
return b ? 0 : -1;
}
const mcl::CurveParam& cp = mcl::getCurveParam(curve);
const mcl::CurveParam* cp = mcl::getCurveParam(curve);
if (cp == 0) return -1;
bool b;
initPairing(&b, cp);
initPairing(&b, *cp);
return b ? 0 : -1;
}
int mclBn_getCurveType()
{
return mcl::bn::BN::param.cp.curveType;
}
int mclBn_getOpUnitSize()
{
return (int)Fp::getUnitSize() * sizeof(mcl::fp::Unit) / sizeof(uint64_t);
@ -113,9 +119,21 @@ mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize)
return Fp::getModulo(buf, maxBufSize);
}
void mclBn_setETHserialization(int ETHserialization)
void mclBn_setETHserialization(int enable)
{
if (mclBn_getCurveType() != MCL_BLS12_381) return;
Fp::setETHserialization(enable == 1);
Fr::setETHserialization(enable == 1);
}
int mclBn_getETHserialization()
{
return Fp::getETHserialization() ? 1 : 0;
}
int mclBn_setMapToMode(int mode)
{
Fp::setETHserialization(ETHserialization == 1);
return setMapToMode(mode) ? 0 : -1;
}
////////////////////////////////////////////////
@ -141,13 +159,24 @@ int mclBnFr_setStr(mclBnFr *x, const char *buf, mclSize bufSize, int ioMode)
}
int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, mclSize bufSize)
{
cast(x)->setArrayMask((const char *)buf, bufSize);
cast(x)->setArrayMask((const uint8_t *)buf, bufSize);
return 0;
}
int mclBnFr_setBigEndianMod(mclBnFr *x, const void *buf, mclSize bufSize)
{
bool b;
cast(x)->setBigEndianMod(&b, (const uint8_t*)buf, bufSize);
return b ? 0 : -1;
}
mclSize mclBnFr_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFr *x)
{
return cast(x)->getLittleEndian((uint8_t*)buf, maxBufSize);
}
int mclBnFr_setLittleEndianMod(mclBnFr *x, const void *buf, mclSize bufSize)
{
bool b;
cast(x)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod);
cast(x)->setArrayMod(&b, (const uint8_t *)buf, bufSize);
return b ? 0 : -1;
}
mclSize mclBnFr_deserialize(mclBnFr *x, const void *buf, mclSize bufSize)
@ -171,6 +200,14 @@ int mclBnFr_isOne(const mclBnFr *x)
{
return cast(x)->isOne();
}
int mclBnFr_isOdd(const mclBnFr *x)
{
return cast(x)->isOdd();
}
int mclBnFr_isNegative(const mclBnFr *x)
{
return cast(x)->isNegative();
}
#ifndef MCL_DONT_USE_CSRPNG
int mclBnFr_setByCSPRNG(mclBnFr *x)
@ -179,6 +216,12 @@ int mclBnFr_setByCSPRNG(mclBnFr *x)
cast(x)->setByCSPRNG(&b);
return b ? 0 : -1;
}
int mclBnFp_setByCSPRNG(mclBnFp *x)
{
bool b;
cast(x)->setByCSPRNG(&b);
return b ? 0 : -1;
}
void mclBn_setRandFunc(void *self, unsigned int (*readFunc)(void *self, void *buf, unsigned int bufSize))
{
mcl::fp::RandGen::setRandFunc(self, readFunc);
@ -230,6 +273,77 @@ void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y)
Fr::div(*cast(z),*cast(x), *cast(y));
}
void mclBnFp_neg(mclBnFp *y, const mclBnFp *x)
{
Fp::neg(*cast(y), *cast(x));
}
void mclBnFp_inv(mclBnFp *y, const mclBnFp *x)
{
Fp::inv(*cast(y), *cast(x));
}
void mclBnFp_sqr(mclBnFp *y, const mclBnFp *x)
{
Fp::sqr(*cast(y), *cast(x));
}
void mclBnFp_add(mclBnFp *z, const mclBnFp *x, const mclBnFp *y)
{
Fp::add(*cast(z),*cast(x), *cast(y));
}
void mclBnFp_sub(mclBnFp *z, const mclBnFp *x, const mclBnFp *y)
{
Fp::sub(*cast(z),*cast(x), *cast(y));
}
void mclBnFp_mul(mclBnFp *z, const mclBnFp *x, const mclBnFp *y)
{
Fp::mul(*cast(z),*cast(x), *cast(y));
}
void mclBnFp_div(mclBnFp *z, const mclBnFp *x, const mclBnFp *y)
{
Fp::div(*cast(z),*cast(x), *cast(y));
}
void mclBnFp2_neg(mclBnFp2 *y, const mclBnFp2 *x)
{
Fp2::neg(*cast(y), *cast(x));
}
void mclBnFp2_inv(mclBnFp2 *y, const mclBnFp2 *x)
{
Fp2::inv(*cast(y), *cast(x));
}
void mclBnFp2_sqr(mclBnFp2 *y, const mclBnFp2 *x)
{
Fp2::sqr(*cast(y), *cast(x));
}
void mclBnFp2_add(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y)
{
Fp2::add(*cast(z),*cast(x), *cast(y));
}
void mclBnFp2_sub(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y)
{
Fp2::sub(*cast(z),*cast(x), *cast(y));
}
void mclBnFp2_mul(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y)
{
Fp2::mul(*cast(z),*cast(x), *cast(y));
}
void mclBnFp2_div(mclBnFp2 *z, const mclBnFp2 *x, const mclBnFp2 *y)
{
Fp2::div(*cast(z),*cast(x), *cast(y));
}
int mclBnFr_squareRoot(mclBnFr *y, const mclBnFr *x)
{
return Fr::squareRoot(*cast(y), *cast(x)) ? 0 : -1;
}
int mclBnFp_squareRoot(mclBnFp *y, const mclBnFp *x)
{
return Fp::squareRoot(*cast(y), *cast(x)) ? 0 : -1;
}
int mclBnFp2_squareRoot(mclBnFp2 *y, const mclBnFp2 *x)
{
return Fp2::squareRoot(*cast(y), *cast(x)) ? 0 : -1;
}
////////////////////////////////////////////////
// set zero
void mclBnG1_clear(mclBnG1 *x)
@ -443,6 +557,10 @@ void mclBnGT_neg(mclBnGT *y, const mclBnGT *x)
Fp12::neg(*cast(y), *cast(x));
}
void mclBnGT_inv(mclBnGT *y, const mclBnGT *x)
{
Fp12::unitaryInv(*cast(y), *cast(x));
}
void mclBnGT_invGeneric(mclBnGT *y, const mclBnGT *x)
{
Fp12::inv(*cast(y), *cast(x));
}
@ -476,6 +594,19 @@ void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y)
Fp12::powGeneric(*cast(z), *cast(x), *cast(y));
}
void mclBnG1_mulVec(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y, mclSize n)
{
G1::mulVec(*cast(z), cast(x), cast(y), n);
}
void mclBnG2_mulVec(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y, mclSize n)
{
G2::mulVec(*cast(z), cast(x), cast(y), n);
}
void mclBnGT_powVec(mclBnGT *z, const mclBnGT *x, const mclBnFr *y, mclSize n)
{
GT::powVec(*cast(z), cast(x), cast(y), n);
}
void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y)
{
pairing(*cast(z), *cast(x), *cast(y));
@ -488,6 +619,10 @@ void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y)
{
millerLoop(*cast(z), *cast(x), *cast(y));
}
void mclBn_millerLoopVec(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y, mclSize n)
{
millerLoopVec(*cast(z), cast(x), cast(y), n);
}
int mclBn_getUint64NumToPrecompute(void)
{
return int(BN::param.precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t));
@ -560,6 +695,15 @@ void mclBn_verifyOrderG2(int doVerify)
verifyOrderG2(doVerify != 0);
}
void mclBnFp_setInt(mclBnFp *y, mclInt x)
{
*cast(y) = x;
}
void mclBnFp_setInt32(mclBnFp *y, int x)
{
*cast(y) = x;
}
mclSize mclBnFp_getStr(char *buf, mclSize maxBufSize, const mclBnFp *x, int ioMode)
{
return cast(x)->getStr(buf, maxBufSize, ioMode);
@ -585,20 +729,52 @@ void mclBnFp_clear(mclBnFp *x)
int mclBnFp_setLittleEndian(mclBnFp *x, const void *buf, mclSize bufSize)
{
cast(x)->setArrayMask((const char *)buf, bufSize);
cast(x)->setArrayMask((const uint8_t *)buf, bufSize);
return 0;
}
int mclBnFp_setLittleEndianMod(mclBnFp *x, const void *buf, mclSize bufSize)
{
bool b;
cast(x)->setArray(&b, (const char *)buf, bufSize, mcl::fp::Mod);
cast(x)->setLittleEndianMod(&b, (const uint8_t*)buf, bufSize);
return b ? 0 : -1;
}
int mclBnFp_setBigEndianMod(mclBnFp *x, const void *buf, mclSize bufSize)
{
bool b;
cast(x)->setBigEndianMod(&b, (const uint8_t*)buf, bufSize);
return b ? 0 : -1;
}
mclSize mclBnFp_getLittleEndian(void *buf, mclSize maxBufSize, const mclBnFp *x)
{
return cast(x)->getLittleEndian((uint8_t*)buf, maxBufSize);
}
int mclBnFp_isValid(const mclBnFp *x)
{
return cast(x)->isValid();
}
int mclBnFp_isEqual(const mclBnFp *x, const mclBnFp *y)
{
return *cast(x) == *cast(y);
}
int mclBnFp_isZero(const mclBnFp *x)
{
return cast(x)->isZero();
}
int mclBnFp_isOne(const mclBnFp *x)
{
return cast(x)->isOne();
}
int mclBnFp_isOdd(const mclBnFp *x)
{
return cast(x)->isOdd();
}
int mclBnFp_isNegative(const mclBnFp *x)
{
return cast(x)->isNegative();
}
int mclBnFp_setHashOf(mclBnFp *x, const void *buf, mclSize bufSize)
{
@ -632,6 +808,14 @@ int mclBnFp2_isEqual(const mclBnFp2 *x, const mclBnFp2 *y)
{
return *cast(x) == *cast(y);
}
int mclBnFp2_isZero(const mclBnFp2 *x)
{
return cast(x)->isZero();
}
int mclBnFp2_isOne(const mclBnFp2 *x)
{
return cast(x)->isOne();
}
int mclBnFp2_mapToG2(mclBnG2 *y, const mclBnFp2 *x)
{

@ -0,0 +1,572 @@
#pragma once
/**
@file
@brief map to G2 on BLS12-381 (must be included from mcl/bn.hpp)
@author MITSUNARI Shigeo(@herumi)
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
ref. https://eprint.iacr.org/2019/403 , https://github.com/algorand/bls_sigs_ref
*/
namespace mcl {
namespace local {
// y^2 = x^3 + 4(1 + i)
template<class F>
struct PointT {
typedef F Fp;
F x, y, z;
static F a_;
static F b_;
static int specialA_;
bool isZero() const
{
return z.isZero();
}
void clear()
{
x.clear();
y.clear();
z.clear();
}
bool isEqual(const PointT<F>& rhs) const
{
return ec::isEqualJacobi(*this, rhs);
}
};
template<class F> F PointT<F>::a_;
template<class F> F PointT<F>::b_;
template<class F> int PointT<F>::specialA_;
} // mcl::local
template<class Fp, class G1, class Fp2, class G2>
struct MapTo_WB19 {
typedef local::PointT<Fp> E1;
typedef local::PointT<Fp2> E2;
mpz_class sqrtConst; // (p^2 - 9) / 16
Fp2 g2A;
Fp2 g2B;
Fp2 root4[4];
Fp2 etas[4];
Fp2 xnum[4];
Fp2 xden[3];
Fp2 ynum[4];
Fp2 yden[4];
Fp g1A, g1B, g1c1, g1c2;
Fp g1xnum[12];
Fp g1xden[11];
Fp g1ynum[16];
Fp g1yden[16];
mpz_class g1cofactor;
int g1Z;
void init()
{
bool b;
g2A.a = 0;
g2A.b = 240;
g2B.a = 1012;
g2B.b = 1012;
E1::a_.clear();
E1::b_ = 4;
E1::specialA_ = ec::Zero;
E2::a_.clear();
E2::b_.a = 4;
E2::b_.b = 4;
E2::specialA_ = ec::Zero;
sqrtConst = Fp::getOp().mp;
sqrtConst *= sqrtConst;
sqrtConst -= 9;
sqrtConst /= 16;
const char *rv1Str = "0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09";
root4[0].a = 1;
root4[0].b.clear();
root4[1].a.clear();
root4[1].b = 1;
root4[2].a.setStr(&b, rv1Str);
assert(b); (void)b;
root4[2].b = root4[2].a;
root4[3].a = root4[2].a;
Fp::neg(root4[3].b, root4[3].a);
const char *ev1Str = "0x699be3b8c6870965e5bf892ad5d2cc7b0e85a117402dfd83b7f4a947e02d978498255a2aaec0ac627b5afbdf1bf1c90";
const char *ev2Str = "0x8157cd83046453f5dd0972b6e3949e4288020b5b8a9cc99ca07e27089a2ce2436d965026adad3ef7baba37f2183e9b5";
const char *ev3Str = "0xab1c2ffdd6c253ca155231eb3e71ba044fd562f6f72bc5bad5ec46a0b7a3b0247cf08ce6c6317f40edbc653a72dee17";
const char *ev4Str = "0xaa404866706722864480885d68ad0ccac1967c7544b447873cc37e0181271e006df72162a3d3e0287bf597fbf7f8fc1";
Fp& ev1 = etas[0].a;
Fp& ev2 = etas[0].b;
Fp& ev3 = etas[2].a;
Fp& ev4 = etas[2].b;
ev1.setStr(&b, ev1Str);
assert(b); (void)b;
ev2.setStr(&b, ev2Str);
assert(b); (void)b;
Fp::neg(etas[1].a, ev2);
etas[1].b = ev1;
ev3.setStr(&b, ev3Str);
assert(b); (void)b;
ev4.setStr(&b, ev4Str);
assert(b); (void)b;
Fp::neg(etas[3].a, ev4);
etas[3].b = ev3;
init_iso3();
{
const char *A = "0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d";
const char *B = "0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0";
const char *c1 = "0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaaa";
const char *c2 = "0x3d689d1e0e762cef9f2bec6130316806b4c80eda6fc10ce77ae83eab1ea8b8b8a407c9c6db195e06f2dbeabc2baeff5";
g1A.setStr(&b, A);
assert(b); (void)b;
g1B.setStr(&b, B);
assert(b); (void)b;
g1c1.setStr(&b, c1);
assert(b); (void)b;
g1c2.setStr(&b, c2);
assert(b); (void)b;
g1Z = 11;
gmp::setStr(&b, g1cofactor, "d201000000010001", 16);
assert(b); (void)b;
}
init_iso11();
}
void initArray(Fp *dst, const char **s, size_t n) const
{
bool b;
for (size_t i = 0; i < n; i++) {
dst[i].setStr(&b, s[i]);
assert(b);
(void)b;
}
}
void init_iso3()
{
const char *tbl[] = {
"0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6",
"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a",
"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e",
"0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d",
"0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f",
"0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706",
"0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be",
"0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c",
"0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f",
"0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3",
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99",
};
bool b;
xnum[0].a.setStr(&b, tbl[0]); assert(b); (void)b;
xnum[0].b = xnum[0].a;
xnum[1].a.clear();
xnum[1].b.setStr(&b, tbl[1]); assert(b); (void)b;
xnum[2].a.setStr(&b, tbl[2]); assert(b); (void)b;
xnum[2].b.setStr(&b, tbl[3]); assert(b); (void)b;
xnum[3].a.setStr(&b, tbl[4]); assert(b); (void)b;
xnum[3].b.clear();
xden[0].a.clear();
xden[0].b.setStr(&b, tbl[5]); assert(b); (void)b;
xden[1].a = 0xc;
xden[1].b.setStr(&b, tbl[6]); assert(b); (void)b;
xden[2].a = 1;
xden[2].b = 0;
ynum[0].a.setStr(&b, tbl[7]); assert(b); (void)b;
ynum[0].b = ynum[0].a;
ynum[1].a.clear();
ynum[1].b.setStr(&b, tbl[8]); assert(b); (void)b;
ynum[2].a.setStr(&b, tbl[9]); assert(b); (void)b;
ynum[2].b.setStr(&b, tbl[10]); assert(b); (void)b;
ynum[3].a.setStr(&b, tbl[11]); assert(b); (void)b;
ynum[3].b.clear();
yden[0].a.setStr(&b, tbl[12]); assert(b); (void)b;
yden[0].b = yden[0].a;
yden[1].a.clear();
yden[1].b.setStr(&b, tbl[13]); assert(b); (void)b;
yden[2].a = 0x12;
yden[2].b.setStr(&b, tbl[14]); assert(b); (void)b;
yden[3].a = 1;
yden[3].b.clear();
}
void init_iso11()
{
const char *xnumStr[] = {
"0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7",
"0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb",
"0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0",
"0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861",
"0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9",
"0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983",
"0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84",
"0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e",
"0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317",
"0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e",
"0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b",
"0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229",
};
const char *xdenStr[] = {
"0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c",
"0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff",
"0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19",
"0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8",
"0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e",
"0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5",
"0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a",
"0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e",
"0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641",
"0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a",
"0x1",
};
const char *ynumStr[] = {
"0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33",
"0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696",
"0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6",
"0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb",
"0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb",
"0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0",
"0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2",
"0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29",
"0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587",
"0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30",
"0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132",
"0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e",
"0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8",
"0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133",
"0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b",
"0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604",
};
const char *ydenStr[] = {
"0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1",
"0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d",
"0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2",
"0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416",
"0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d",
"0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac",
"0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c",
"0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9",
"0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a",
"0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55",
"0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8",
"0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092",
"0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc",
"0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7",
"0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f",
"0x1",
};
initArray(g1xnum, xnumStr, CYBOZU_NUM_OF_ARRAY(xnumStr));
initArray(g1xden, xdenStr, CYBOZU_NUM_OF_ARRAY(xdenStr));
initArray(g1ynum, ynumStr, CYBOZU_NUM_OF_ARRAY(ynumStr));
initArray(g1yden, ydenStr, CYBOZU_NUM_OF_ARRAY(ydenStr));
}
template<class F, size_t N>
void evalPoly(F& y, const F& x, const F *zpows, const F (&cof)[N]) const
{
y = cof[N - 1]; // always zpows[0] = 1
for (size_t i = 1; i < N; i++) {
y *= x;
F t;
F::mul(t, zpows[i - 1], cof[N - 1 - i]);
y += t;
}
}
// refer (xnum, xden, ynum, yden)
void iso3(G2& Q, const E2& P) const
{
Fp2 zpows[3];
Fp2::sqr(zpows[0], P.z);
Fp2::sqr(zpows[1], zpows[0]);
Fp2::mul(zpows[2], zpows[1], zpows[0]);
Fp2 mapvals[4];
evalPoly(mapvals[0], P.x, zpows, xnum);
evalPoly(mapvals[1], P.x, zpows, xden);
evalPoly(mapvals[2], P.x, zpows, ynum);
evalPoly(mapvals[3], P.x, zpows, yden);
mapvals[1] *= zpows[0];
mapvals[2] *= P.y;
mapvals[3] *= zpows[0];
mapvals[3] *= P.z;
Fp2::mul(Q.z, mapvals[1], mapvals[3]);
Fp2::mul(Q.x, mapvals[0], mapvals[3]);
Q.x *= Q.z;
Fp2 t;
Fp2::sqr(t, Q.z);
Fp2::mul(Q.y, mapvals[2], mapvals[1]);
Q.y *= t;
}
template<class X, class C, size_t N>
X evalPoly2(const X& x, const C (&c)[N]) const
{
X ret = c[N - 1];
for (size_t i = 1; i < N; i++) {
ret *= x;
ret += c[N - 1 - i];
}
return ret;
}
// refer (g1xnum, g1xden, g1ynum, g1yden)
void iso11(G1& Q, E1& P) const
{
ec::normalizeJacobi(P);
Fp xn, xd, yn, yd;
xn = evalPoly2(P.x, g1xnum);
xd = evalPoly2(P.x, g1xden);
yn = evalPoly2(P.x, g1ynum);
yd = evalPoly2(P.x, g1yden);
/*
[xn/xd:y * yn/yd:1] = [xn xd yd^2:y yn xd^3 yd^2:xd yd]
=[xn yd z:y yn xd z^2:z] where z = xd yd
*/
Fp::mul(Q.z, xd, yd);
Fp::mul(Q.x, xn, yd);
Q.x *= Q.z;
Fp::mul(Q.y, P.y, yn);
Q.y *= xd;
Fp::sqr(xd, Q.z);
Q.y *= xd;
}
/*
xi = -2-i
(a+bi)*(-2-i) = (b-2a)-(a+2b)i
*/
void mul_xi(Fp2& y, const Fp2& x) const
{
Fp t;
Fp::sub(t, x.b, x.a);
t -= x.a;
Fp::add(y.b, x.b, x.b);
y.b += x.a;
Fp::neg(y.b, y.b);
y.a = t;
}
bool isNegSign(const Fp& x) const
{
return x.isOdd();
}
bool isNegSign(const Fp2& x) const
{
bool sign0 = isNegSign(x.a);
bool zero0 = x.a.isZero();
bool sign1 = isNegSign(x.b);
return sign0 || (zero0 & sign1);
}
// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-07#appendix-D.3.5
void sswuG1(Fp& xn, Fp& xd, Fp& y, const Fp& u) const
{
const Fp& A = g1A;
const Fp& B = g1B;
const Fp& c1 = g1c1;
const Fp& c2 = g1c2;
const int Z = g1Z;
Fp u2, u2Z, t, t2, t3;
Fp::sqr(u2, u);
Fp::mulUnit(u2Z, u2, Z);
Fp::sqr(t, u2Z);
Fp::add(xd, t, u2Z);
if (xd.isZero()) {
Fp::mulUnit(xd, A, Z);
xn = B;
} else {
Fp::add(xn, xd, Fp::one());
xn *= B;
xd *= A;
Fp::neg(xd, xd);
}
Fp::sqr(t, xd);
Fp::mul(t2, t, xd);
t *= A;
Fp::sqr(t3, xn);
t3 += t;
t3 *= xn;
Fp::mul(t, t2, B);
t3 += t;
Fp::sqr(y, t2);
Fp::mul(t, t3, t2);
y *= t;
Fp::pow(y, y, c1);
y *= t;
Fp::sqr(t, y);
t *= t2;
if (t != t3) {
xn *= u2Z;
y *= c2;
y *= u2;
y *= u;
}
if (isNegSign(u) != isNegSign(y)) {
Fp::neg(y, y);
}
}
void sswuG1(E1& pt, const Fp& u) const
{
Fp xn, y;
Fp& xd = pt.z;
sswuG1(xn, xd, y, u);
Fp::mul(pt.x, xn, xd);
Fp::sqr(pt.y, xd);
pt.y *= xd;
pt.y *= y;
}
// https://github.com/algorand/bls_sigs_ref
void sswuG2(E2& P, const Fp2& t) const
{
Fp2 t2, t2xi;
Fp2::sqr(t2, t);
Fp2 den, den2;
mul_xi(t2xi, t2);
den = t2xi;
Fp2::sqr(den2, den);
// (t^2 * xi)^2 + (t^2 * xi)
den += den2;
Fp2 x0_num, x0_den;
Fp2::add(x0_num, den, 1);
x0_num *= g2B;
if (den.isZero()) {
mul_xi(x0_den, g2A);
} else {
Fp2::mul(x0_den, -g2A, den);
}
Fp2 x0_den2, x0_den3, gx0_den, gx0_num;
Fp2::sqr(x0_den2, x0_den);
Fp2::mul(x0_den3, x0_den2, x0_den);
gx0_den = x0_den3;
Fp2::mul(gx0_num, g2B, gx0_den);
Fp2 tmp, tmp1, tmp2;
Fp2::mul(tmp, g2A, x0_num);
tmp *= x0_den2;
gx0_num += tmp;
Fp2::sqr(tmp, x0_num);
tmp *= x0_num;
gx0_num += tmp;
Fp2::sqr(tmp1, gx0_den); // x^2
Fp2::sqr(tmp2, tmp1); // x^4
tmp1 *= tmp2;
tmp1 *= gx0_den; // x^7
Fp2::mul(tmp2, gx0_num, tmp1);
tmp1 *= tmp2;
tmp1 *= gx0_den;
Fp2 candi;
Fp2::pow(candi, tmp1, sqrtConst);
candi *= tmp2;
bool isNegT = isNegSign(t);
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(root4); i++) {
Fp2::mul(P.y, candi, root4[i]);
Fp2::sqr(tmp, P.y);
tmp *= gx0_den;
if (tmp == gx0_num) {
if (isNegSign(P.y) != isNegT) {
Fp2::neg(P.y, P.y);
}
Fp2::mul(P.x, x0_num, x0_den);
P.y *= x0_den3;
P.z = x0_den;
return;
}
}
Fp2 x1_num, x1_den, gx1_num, gx1_den;
Fp2::mul(x1_num, t2xi, x0_num);
x1_den = x0_den;
Fp2::mul(gx1_num, den2, t2xi);
gx1_num *= gx0_num;
gx1_den = gx0_den;
candi *= t2;
candi *= t;
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(etas); i++) {
Fp2::mul(P.y, candi, etas[i]);
Fp2::sqr(tmp, P.y);
tmp *= gx1_den;
if (tmp == gx1_num) {
if (isNegSign(P.y) != isNegT) {
Fp2::neg(P.y, P.y);
}
Fp2::mul(P.x, x1_num, x1_den);
Fp2::sqr(tmp, x1_den);
P.y *= tmp;
P.y *= x1_den;
P.z = x1_den;
return;
}
}
assert(0);
}
template<class T>
void put(const T& P) const
{
const int base = 10;
printf("x=%s\n", P.x.getStr(base).c_str());
printf("y=%s\n", P.y.getStr(base).c_str());
printf("z=%s\n", P.z.getStr(base).c_str());
}
void Fp2ToG2(G2& P, const Fp2& t, const Fp2 *t2 = 0) const
{
E2 Pp;
sswuG2(Pp, t);
if (t2) {
E2 P2;
sswuG2(P2, *t2);
ec::addJacobi(Pp, Pp, P2);
}
iso3(P, Pp);
mcl::local::mulByCofactorBLS12fast(P, P);
}
void hashToFp2(Fp2 out[2], const void *msg, size_t msgSize, const void *dst, size_t dstSize) const
{
uint8_t md[256];
mcl::fp::expand_message_xmd(md, sizeof(md), msg, msgSize, dst, dstSize);
Fp *x = out[0].getFp0();
for (size_t i = 0; i < 4; i++) {
bool b;
x[i].setBigEndianMod(&b, &md[64 * i], 64);
assert(b); (void)b;
}
}
void msgToG2(G2& out, const void *msg, size_t msgSize, const void *dst, size_t dstSize) const
{
Fp2 t[2];
hashToFp2(t, msg, msgSize, dst, dstSize);
Fp2ToG2(out, t[0], &t[1]);
}
void msgToG2(G2& out, const void *msg, size_t msgSize) const
{
const char *dst = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
const size_t dstSize = strlen(dst);
msgToG2(out, msg, msgSize, dst, dstSize);
}
void FpToG1(G1& out, const Fp& u0, const Fp *u1 = 0) const
{
E1 P1;
sswuG1(P1, u0);
if (u1) {
E1 P2;
sswuG1(P2, *u1);
ec::addJacobi(P1, P1, P2);
}
iso11(out, P1);
G1::mulGeneric(out, out, g1cofactor);
}
void msgToG1(G1& out, const void *msg, size_t msgSize, const char *dst, size_t dstSize) const
{
uint8_t md[128];
mcl::fp::expand_message_xmd(md, sizeof(md), msg, msgSize, dst, dstSize);
Fp u[2];
for (size_t i = 0; i < 2; i++) {
bool b;
u[i].setBigEndianMod(&b, &md[64 * i], 64);
assert(b); (void)b;
}
FpToG1(out, u[0], &u[1]);
}
void msgToG1(G1& out, const void *msg, size_t msgSize) const
{
const char *dst = "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_POP_";
const size_t dstSize = strlen(dst);
msgToG1(out, msg, msgSize, dst, dstSize);
}
};
} // mcl

@ -14,8 +14,11 @@
#define MCL_DONT_USE_XBYAK
#define MCL_DONT_USE_OPENSSL
#endif
#if !defined(MCL_DONT_USE_XBYAK) && (defined(_WIN64) || defined(__x86_64__)) && (MCL_SIZEOF_UNIT == 8)
#if !defined(MCL_DONT_USE_XBYAK) && (defined(_WIN64) || defined(__x86_64__)) && (MCL_SIZEOF_UNIT == 8) && !defined(MCL_STATIC_CODE)
#define MCL_USE_XBYAK
#endif
#if defined(MCL_USE_XBYAK) || defined(MCL_STATIC_CODE)
#define MCL_X64_ASM
#define MCL_XBYAK_DIRECT_CALL
#endif
@ -23,7 +26,7 @@
namespace mcl {
static const int version = 0x094; /* 0xABC = A.BC */
static const int version = 0x151; /* 0xABC = A.BC */
/*
specifies available string format mode for X::setIoMode()
@ -101,16 +104,29 @@ enum IoMode {
IoSerialize = 512, // use MBS for 1-bit y
IoFixedSizeByteSeq = IoSerialize, // obsolete
IoEcProj = 1024, // projective or jacobi coordinate
IoSerializeHexStr = 2048 // printable hex string
IoSerializeHexStr = 2048, // printable hex string
IoEcAffineSerialize = 4096 // serialize [x:y]
};
namespace fp {
inline bool isIoSerializeMode(int ioMode)
{
return ioMode & (IoArray | IoArrayRaw | IoSerialize | IoEcAffineSerialize | IoSerializeHexStr);
}
const size_t UnitBitSize = sizeof(Unit) * 8;
const size_t maxUnitSize = (MCL_MAX_BIT_SIZE + UnitBitSize - 1) / UnitBitSize;
#define MCL_MAX_UNIT_SIZE ((MCL_MAX_BIT_SIZE + MCL_UNIT_BIT_SIZE - 1) / MCL_UNIT_BIT_SIZE)
const size_t maxMulVecN = 32; // inner loop of mulVec
#ifndef MCL_MAX_MUL_VEC_NGLV
#define MCL_MAX_MUL_VEC_NGLV 16
#endif
const size_t maxMulVecNGLV = MCL_MAX_MUL_VEC_NGLV; // inner loop of mulVec with GLV
struct FpGenerator;
struct Op;
@ -157,13 +173,6 @@ enum PrimeMode {
PM_NIST_P521
};
enum MaskMode {
NoMask = 0, // throw if greater or equal
SmallMask = 1, // 1-bit smaller mask if greater or equal
MaskAndMod = 2, // mask and substract if greater or equal
Mod = 3 // mod p
};
struct Op {
/*
don't change the layout of rp and p
@ -175,6 +184,7 @@ struct Op {
uint32_t pmod4;
mcl::SquareRoot sq;
mcl::Modp modp;
mcl::SmallModp smallModp;
Unit half[maxUnitSize]; // (p + 1) / 2
Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery)
/*
@ -189,6 +199,8 @@ struct Op {
Unit R3[maxUnitSize];
#ifdef MCL_USE_XBYAK
FpGenerator *fg;
#endif
#ifdef MCL_X64_ASM
mcl::Array<Unit> invTbl;
#endif
void3u fp_addA_;
@ -196,18 +208,20 @@ struct Op {
void2u fp_negA_;
void3u fp_mulA_;
void2u fp_sqrA_;
void2u fp_mul2A_;
void2u fp_mul9A_;
void3u fp2_addA_;
void3u fp2_subA_;
void2u fp2_negA_;
void3u fp2_mulA_;
void2u fp2_sqrA_;
void2u fp2_mul2A_;
void3u fpDbl_addA_;
void3u fpDbl_subA_;
void3u fpDbl_mulPreA_;
void2u fpDbl_sqrPreA_;
void2u fpDbl_modA_;
void3u fp2Dbl_mulPreA_;
void2u fp2Dbl_sqrPreA_;
void2u fp2Dbl_mul_xiA_;
size_t maxN;
size_t N;
size_t bitSize;
@ -220,6 +234,7 @@ struct Op {
void4u fp_sub;
void4u fp_mul;
void3u fp_sqr;
void3u fp_mul2;
void2uOp fp_invOp;
void2uIu fp_mulUnit; // fpN1_mod + fp_mulUnitPre
@ -243,7 +258,6 @@ struct Op {
*/
int xi_a; // xi = xi_a + u
void4u fp2_mulNF;
void2u fp2_inv;
void2u fp2_mul_xiA_;
uint32_t (*hash)(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize);
@ -275,7 +289,7 @@ struct Op {
memset(one, 0, sizeof(one));
memset(R2, 0, sizeof(R2));
memset(R3, 0, sizeof(R3));
#ifdef MCL_USE_XBYAK
#ifdef MCL_X64_ASM
invTbl.clear();
#endif
fp_addA_ = 0;
@ -283,18 +297,20 @@ struct Op {
fp_negA_ = 0;
fp_mulA_ = 0;
fp_sqrA_ = 0;
fp_mul2A_ = 0;
fp_mul9A_ = 0;
fp2_addA_ = 0;
fp2_subA_ = 0;
fp2_negA_ = 0;
fp2_mulA_ = 0;
fp2_sqrA_ = 0;
fp2_mul2A_ = 0;
fpDbl_addA_ = 0;
fpDbl_subA_ = 0;
fpDbl_mulPreA_ = 0;
fpDbl_sqrPreA_ = 0;
fpDbl_modA_ = 0;
fp2Dbl_mulPreA_ = 0;
fp2Dbl_sqrPreA_ = 0;
fp2Dbl_mul_xiA_ = 0;
maxN = 0;
N = 0;
bitSize = 0;
@ -307,6 +323,7 @@ struct Op {
fp_sub = 0;
fp_mul = 0;
fp_sqr = 0;
fp_mul2 = 0;
fp_invOp = 0;
fp_mulUnit = 0;
@ -327,7 +344,6 @@ struct Op {
xi_a = 0;
fp2_mulNF = 0;
fp2_inv = 0;
fp2_mul_xiA_ = 0;
hash = 0;
@ -363,13 +379,14 @@ private:
inline const char* getIoSeparator(int ioMode)
{
return (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr)) ? "" : " ";
return (ioMode & (IoArray | IoArrayRaw | IoSerialize | IoSerializeHexStr | IoEcAffineSerialize)) ? "" : " ";
}
inline void dump(const char *s, size_t n)
inline void dump(const void *buf, size_t n)
{
const uint8_t *s = (const uint8_t *)buf;
for (size_t i = 0; i < n; i++) {
printf("%02x ", (uint8_t)s[i]);
printf("%02x ", s[i]);
}
printf("\n");
}

@ -84,12 +84,39 @@ struct Operator : public E {
{
powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, true);
}
static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime))
static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime), size_t g(T& z, const T *xVec, const mpz_class *yVec, size_t n) = 0)
{
powArrayGLV = f;
powVecNGLV = g;
}
static const size_t powVecMaxN = 16;
template<class tag, size_t maxBitSize, template<class _tag, size_t _maxBitSize>class FpT>
static void powVec(T& z, const T* xVec, const FpT<tag, maxBitSize> *yVec, size_t n)
{
assert(powVecNGLV);
T r;
r.setOne();
const size_t N = mcl::fp::maxMulVecNGLV;
mpz_class myVec[N];
while (n > 0) {
T t;
size_t tn = fp::min_(n, N);
for (size_t i = 0; i < tn; i++) {
bool b;
yVec[i].getMpz(&b, myVec[i]);
assert(b); (void)b;
}
size_t done = powVecNGLV(t, xVec, myVec, tn);
r *= t;
xVec += done;
yVec += done;
n -= done;
}
z = r;
}
private:
static void (*powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);
static size_t (*powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n);
static void powArray(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)
{
if (powArrayGLV && (constTime || yn > 1)) {
@ -117,6 +144,9 @@ private:
template<class T, class E>
void (*Operator<T, E>::powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime);
template<class T, class E>
size_t (*Operator<T, E>::powVecNGLV)(T& z, const T* xVec, const mpz_class *yVec, size_t n);
/*
T must have save and load
*/
@ -154,6 +184,20 @@ struct Serializable : public E {
getStr(str, ioMode);
return str;
}
std::string serializeToHexStr() const
{
std::string str(sizeof(T) * 2, 0);
size_t n = serialize(&str[0], str.size(), IoSerializeHexStr);
str.resize(n);
return str;
}
#ifndef CYBOZU_DONT_USE_EXCEPTION
void deserializeHexStr(const std::string& str)
{
size_t n = deserialize(str.c_str(), str.size(), IoSerializeHexStr);
if (n == 0) throw cybozu::Exception("bad str") << str;
}
#endif
#endif
// return written bytes
size_t serialize(void *buf, size_t maxBufSize, int ioMode = IoSerialize) const

@ -74,6 +74,18 @@ typedef struct {
typedef struct {
mclBnFr d[7];
} sheZkpBinEq;
typedef struct {
mclBnFr d[2];
} sheZkpDec;
typedef struct {
mclBnGT d[4];
} sheAuxiliaryForZkpDecGT;
typedef struct {
mclBnFr d[4];
} sheZkpDecGT;
/*
initialize this library
call this once before using the other functions
@ -96,6 +108,8 @@ MCLSHE_DLL_API mclSize sheCipherTextGTSerialize(void *buf, mclSize maxBufSize, c
MCLSHE_DLL_API mclSize sheZkpBinSerialize(void *buf, mclSize maxBufSize, const sheZkpBin *zkp);
MCLSHE_DLL_API mclSize sheZkpEqSerialize(void *buf, mclSize maxBufSize, const sheZkpEq *zkp);
MCLSHE_DLL_API mclSize sheZkpBinEqSerialize(void *buf, mclSize maxBufSize, const sheZkpBinEq *zkp);
MCLSHE_DLL_API mclSize sheZkpDecSerialize(void *buf, mclSize maxBufSize, const sheZkpDec *zkp);
MCLSHE_DLL_API mclSize sheZkpDecGTSerialize(void *buf, mclSize maxBufSize, const sheZkpDecGT *zkp);
// return read byte size if sucess else 0
MCLSHE_DLL_API mclSize sheSecretKeyDeserialize(sheSecretKey* sec, const void *buf, mclSize bufSize);
@ -106,6 +120,8 @@ MCLSHE_DLL_API mclSize sheCipherTextGTDeserialize(sheCipherTextGT* c, const void
MCLSHE_DLL_API mclSize sheZkpBinDeserialize(sheZkpBin* zkp, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpEqDeserialize(sheZkpEq* zkp, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpBinEqDeserialize(sheZkpBinEq* zkp, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpDecDeserialize(sheZkpDec* zkp, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpDecGTDeserialize(sheZkpDecGT* zkp, const void *buf, mclSize bufSize);
/*
set secretKey if system has /dev/urandom or CryptGenRandom
@ -115,6 +131,8 @@ MCLSHE_DLL_API int sheSecretKeySetByCSPRNG(sheSecretKey *sec);
MCLSHE_DLL_API void sheGetPublicKey(shePublicKey *pub, const sheSecretKey *sec);
MCLSHE_DLL_API void sheGetAuxiliaryForZkpDecGT(sheAuxiliaryForZkpDecGT *aux, const shePublicKey *pub);
/*
make table to decode DLP
return 0 if success
@ -192,6 +210,13 @@ MCLSHE_DLL_API int shePrecomputedPublicKeyEncWithZkpBinEq(sheCipherTextG1 *c1, s
MCLSHE_DLL_API int sheEncWithZkpEq(sheCipherTextG1 *c1, sheCipherTextG2 *c2, sheZkpEq *zkp, const shePublicKey *pub, mclInt m);
MCLSHE_DLL_API int shePrecomputedPublicKeyEncWithZkpEq(sheCipherTextG1 *c1, sheCipherTextG2 *c2, sheZkpEq *zkp, const shePrecomputedPublicKey *ppub, mclInt m);
/*
Zkp s.t. Dec(c) = m
return 0 if success
*/
MCLSHE_DLL_API int sheDecWithZkpDecG1(mclInt *m, sheZkpDec *zkp, const sheSecretKey *sec, const sheCipherTextG1 *c, const shePublicKey *pub);
MCLSHE_DLL_API int sheDecWithZkpDecGT(mclInt *m, sheZkpDecGT *zkp, const sheSecretKey *sec, const sheCipherTextGT *c, const sheAuxiliaryForZkpDecGT *aux);
/*
decode c and set m
return 0 if success
@ -211,6 +236,8 @@ MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpBinG1(const shePrecomputedPub
MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpBinG2(const shePrecomputedPublicKey *ppub, const sheCipherTextG2 *c, const sheZkpBin *zkp);
MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpEq(const shePrecomputedPublicKey *ppub, const sheCipherTextG1 *c1, const sheCipherTextG2 *c2, const sheZkpEq *zkp);
MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpBinEq(const shePrecomputedPublicKey *ppub, const sheCipherTextG1 *c1, const sheCipherTextG2 *c2, const sheZkpBinEq *zkp);
MCLSHE_DLL_API int sheVerifyZkpDecG1(const shePublicKey *pub, const sheCipherTextG1 *c1, mclInt m, const sheZkpDec *zkp);
MCLSHE_DLL_API int sheVerifyZkpDecGT(const sheAuxiliaryForZkpDecGT *aux, const sheCipherTextGT *ct, mclInt m, const sheZkpDecGT *zkp);
/*
decode c via GT and set m
return 0 if success

@ -26,6 +26,8 @@
#include <mcl/window_method.hpp>
#include <cybozu/endian.hpp>
#include <cybozu/serializer.hpp>
#include <cybozu/sha2.hpp>
#include <mcl/ecparam.hpp>
namespace mcl { namespace she {
@ -324,6 +326,26 @@ int log(const G& P, const G& xP)
throw cybozu::Exception("she:log:not found");
}
struct Hash {
cybozu::Sha256 h_;
template<class T>
Hash& operator<<(const T& t)
{
char buf[sizeof(T)];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
t.save(os);
h_.update(buf, os.getPos());
return *this;
}
template<class F>
void get(F& x)
{
uint8_t md[32];
h_.digest(md, sizeof(md), 0, 0);
x.setArrayMask(md, sizeof(md));
}
};
} // mcl::she::local
template<size_t dummyInpl = 0>
@ -366,11 +388,17 @@ private:
public:
const G& getS() const { return S_; }
const G& getT() const { return T_; }
G& getNonConstRefS() { return S_; }
G& getNonConstRefT() { return T_; }
void clear()
{
S_.clear();
T_.clear();
}
bool isValid() const
{
return S_.isValid() && T_.isValid();
}
static void add(CipherTextAT& z, const CipherTextAT& x, const CipherTextAT& y)
{
/*
@ -537,6 +565,8 @@ private:
struct ZkpBinTag;
struct ZkpEqTag; // d_[] = { c, sp, ss, sm }
struct ZkpBinEqTag; // d_[] = { d0, d1, sp0, sp1, ss, sp, sm }
struct ZkpDecTag; // d_[] = { c, h }
struct ZkpDecGTTag; // d_[] = { d1, d2, d3, h }
public:
/*
Zkp for m = 0 or 1
@ -550,9 +580,66 @@ public:
Zkp for (m = 0 or 1) and decG1(c1) == decG2(c2)
*/
typedef ZkpT<ZkpBinEqTag, 7> ZkpBinEq;
/*
Zkp for Dec(c) = m for c in G1
*/
typedef ZkpT<ZkpDecTag, 2> ZkpDec;
/*
Zkp for Dec(c) = m for c in GT
*/
typedef ZkpT<ZkpDecGTTag, 4> ZkpDecGT;
typedef CipherTextAT<G1> CipherTextG1;
typedef CipherTextAT<G2> CipherTextG2;
/*
auxiliary for ZkpDecGT
@note GT is multiplicative group though treating GT as additive group in comment
*/
struct AuxiliaryForZkpDecGT {
GT R_[4]; // [R = e(R, Q), xR, yR, xyR]
// dst = v[1] a[0] + v[0] a[1] - v[2] a[2]
void f(GT& dst, const GT *v, const Fr *a) const
{
GT t;
GT::pow(dst, v[0], a[1]);
GT::pow(t, v[1], a[0]);
dst *= t;
GT::pow(t, v[2], a[2]);
GT::unitaryInv(t, t);
dst *= t;
}
bool verify(const CipherTextGT& c, int64_t m, const ZkpDecGT& zkp) const
{
const Fr *d = &zkp.d_[0];
const Fr &h = zkp.d_[3];
GT A[4];
GT t;
GT::pow(t, R_[0], m); // m R
GT::unitaryInv(t, t);
GT::mul(A[0], c.g_[0], t);
A[1] = c.g_[1];
A[2] = c.g_[2];
A[3] = c.g_[3];
GT B[3], X;
for (int i = 0; i < 3; i++) {
GT::pow(B[i], R_[0], d[i]);
GT::pow(t, R_[i+1], h);
GT::unitaryInv(t, t);
B[i] *= t;
}
f(X, A + 1, zkp.d_);
GT::pow(t, A[0], h);
GT::unitaryInv(t, t);
X *= t;
local::Hash hash;
hash << R_[1] << R_[2] << R_[3] << A[0] << A[1] << A[2] << A[3] << B[0] << B[1] << B[2] << X;
Fr h2;
hash.get(h2);
return h == h2;
}
};
static void init(const mcl::CurveParam& cp = mcl::BN254, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
{
@ -576,13 +663,7 @@ public:
*/
static void initG1only(const mcl::EcParam& para, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
{
Fp::init(para.p);
Fr::init(para.n);
G1::init(para.a, para.b);
const Fp x0(para.gx);
const Fp y0(para.gy);
P_.set(x0, y0);
mcl::initCurve<G1, Fr>(para.curveType, &P_);
setRangeForG1DLP(hashSize);
useDecG1ViaGT_ = false;
useDecG2ViaGT_ = false;
@ -774,6 +855,88 @@ public:
return isZero(c.a_);
}
}
int64_t decWithZkpDec(bool *pok, ZkpDec& zkp, const CipherTextG1& c, const PublicKey& pub) const
{
/*
c = (S, T)
S = mP + rxP
T = rP
R = S - xT = mP
*/
G1 R;
G1::mul(R, c.T_, x_);
G1::sub(R, c.S_, R);
int64_t m = PhashTbl_.log(R, pok);
if (!*pok) return 0;
const G1& P1 = P_;
const G1& P2 = c.T_; // rP
const G1& A1 = pub.xP_;
G1 A2;
G1::sub(A2, c.S_, R); // rxP
Fr b;
b.setRand();
G1 B1, B2;
G1::mul(B1, P1, b);
G1::mul(B2, P2, b);
Fr& d = zkp.d_[0];
Fr& h = zkp.d_[1];
local::Hash hash;
hash << P2 << A1 << A2 << B1 << B2;
hash.get(h);
Fr::mul(d, h, x_);
d += b;
return m;
}
// @note GT is multiplicative group though treating GT as additive group in comment
int64_t decWithZkpDec(bool *pok, ZkpDecGT& zkp, const CipherTextGT& c, const AuxiliaryForZkpDecGT& aux) const
{
int64_t m = dec(c, pok);
if (!*pok) return 0;
// A = c - Enc(m; 0, 0, 0) = c - (m R, 0, 0, 0)
GT A[4];
GT t;
GT::pow(t, aux.R_[0], m); // m R
GT::unitaryInv(t, t);
GT::mul(A[0], c.g_[0], t);
A[1] = c.g_[1];
A[2] = c.g_[2];
A[3] = c.g_[3];
// dec(A) = 0
Fr b[3];
GT B[3], X;
for (int i = 0; i < 3; i++) {
b[i].setByCSPRNG();
GT::pow(B[i], aux.R_[0], b[i]);
}
aux.f(X, A + 1, b);
local::Hash hash;
hash << aux.R_[1] << aux.R_[2] << aux.R_[3] << A[0] << A[1] << A[2] << A[3] << B[0] << B[1] << B[2] << X;
Fr *d = &zkp.d_[0];
Fr &h = zkp.d_[3];
hash.get(h);
Fr::mul(d[0], h, x_); // h x
Fr::mul(d[1], h, y_); // h y
Fr::mul(d[2], d[1], x_); // h xy
for (int i = 0; i < 3; i++) {
d[i] += b[i];
}
return m;
}
int64_t decWithZkpDec(ZkpDec& zkp, const CipherTextG1& c, const PublicKey& pub) const
{
bool b;
int64_t ret = decWithZkpDec(&b, zkp, c, pub);
if (!b) throw cybozu::Exception("she:SecretKey:decWithZkpDec");
return ret;
}
int64_t decWithZkpDec(ZkpDecGT& zkp, const CipherTextGT& c, const AuxiliaryForZkpDecGT& aux) const
{
bool b;
int64_t ret = decWithZkpDec(&b, zkp, c, aux);
if (!b) throw cybozu::Exception("she:SecretKey:decWithZkpDec");
return ret;
}
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
@ -886,16 +1049,10 @@ private:
r.setRand();
Pmul.mul(static_cast<I&>(R[0][m]), r); // R[0][m] = r P
xPmul.mul(R[1][m], r); // R[1][m] = r xP
char buf[sizeof(G) * 2];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S.save(os);
T.save(os);
R[0][0].save(os);
R[0][1].save(os);
R[1][0].save(os);
R[1][1].save(os);
Fr c;
c.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S << T << R[0][0] << R[0][1] << R[1][0] << R[1][1];
hash.get(c);
d[m] = c - d[1-m];
s[m] = r + d[m] * encRand;
}
@ -925,16 +1082,10 @@ private:
G::sub(T2, S, P);
G::mul(T2, T2, d[1]);
G::sub(R[1][1], T1, T2);
char buf[sizeof(G) * 2];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S.save(os);
T.save(os);
R[0][0].save(os);
R[0][1].save(os);
R[1][0].save(os);
R[1][1].save(os);
Fr c;
c.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S << T << R[0][0] << R[0][1] << R[1][0] << R[1][1];
hash.get(c);
return c == d[0] + d[1];
}
/*
@ -956,21 +1107,13 @@ private:
G2 R3, R4;
ElGamalEnc(R1, R2, rm, Pmul, xPmul, &rp);
ElGamalEnc(R3, R4, rm, Qmul, yQmul, &rs);
char buf[sizeof(G1) * 4 + sizeof(G2) * 4];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S1.save(os);
T1.save(os);
S2.save(os);
T2.save(os);
R1.save(os);
R2.save(os);
R3.save(os);
R4.save(os);
Fr& c = zkp.d_[0];
Fr& sp = zkp.d_[1];
Fr& ss = zkp.d_[2];
Fr& sm = zkp.d_[3];
c.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S1 << T1 << S2 << T2 << R1 << R2 << R3 << R4;
hash.get(c);
Fr::mul(sp, c, p);
sp += rp;
Fr::mul(ss, c, s);
@ -997,18 +1140,10 @@ private:
R3 -= X2;
G2::mul(X2, T2, c);
R4 -= X2;
char buf[sizeof(G1) * 4 + sizeof(G2) * 4];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S1.save(os);
T1.save(os);
S2.save(os);
T2.save(os);
R1.save(os);
R2.save(os);
R3.save(os);
R4.save(os);
Fr c2;
c2.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S1 << T1 << S2 << T2 << R1 << R2 << R3 << R4;
hash.get(c2);
return c == c2;
}
/*
@ -1052,20 +1187,10 @@ private:
G2 R5, R6;
ElGamalEnc(R4, R3, rm, Pmul, xPmul, &rp);
ElGamalEnc(R6, R5, rm, Qmul, yQmul, &rs);
char buf[sizeof(Fp) * 12];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S1.save(os);
T1.save(os);
R1[0].save(os);
R1[1].save(os);
R2[0].save(os);
R2[1].save(os);
R3.save(os);
R4.save(os);
R5.save(os);
R6.save(os);
Fr c;
c.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S1 << T1 << R1[0] << R1[1] << R2[0] << R2[1] << R3 << R4 << R5 << R6;
hash.get(c);
Fr::sub(d[m], c, d[1-m]);
Fr::mul(spm[m], d[m], p);
spm[m] += rpm;
@ -1112,20 +1237,10 @@ private:
R5 -= X2;
G2::mul(X2, S2, c);
R6 -= X2;
char buf[sizeof(Fp) * 12];
cybozu::MemoryOutputStream os(buf, sizeof(buf));
S1.save(os);
T1.save(os);
R1[0].save(os);
R1[1].save(os);
R2[0].save(os);
R2[1].save(os);
R3.save(os);
R4.save(os);
R5.save(os);
R6.save(os);
Fr c2;
c2.setHashOf(buf, os.getPos());
local::Hash hash;
hash << S1 << T1 << R1[0] << R1[1] << R2[0] << R2[1] << R3 << R4 << R5 << R6;
hash.get(c2);
return c == c2;
}
/*
@ -1266,6 +1381,13 @@ public:
ElGamalEnc(c.S_, c.T_, m, QhashTbl_.getWM(), yQmul);
}
public:
void getAuxiliaryForZkpDecGT(AuxiliaryForZkpDecGT& aux) const
{
aux.R_[0] = ePQ_;
pairing(aux.R_[1], xP_, Q_);
pairing(aux.R_[2], P_, yQ_);
pairing(aux.R_[3], xP_, yQ_);
}
void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, int m) const
{
Fr encRand;
@ -1287,6 +1409,33 @@ public:
const MulG<G1> xPmul(xP_);
return verifyZkpBin(c.S_, c.T_, P_, zkp, PhashTbl_.getWM(), xPmul);
}
bool verify(const CipherTextG1& c, int64_t m, const ZkpDec& zkp) const
{
/*
Enc(m;r) - Enc(m;0) = (S, T) - (mP, 0) = (S - mP, T)
*/
const Fr& d = zkp.d_[0];
const Fr& h = zkp.d_[1];
const G1& P1 = P_;
const G1& P2 = c.T_; // rP
const G1& A1 = xP_;
G1 A2;
G1::mul(A2, P_, m);
// PhashTbl_.getWM().mul(A2, m);
G1::sub(A2, c.S_, A2); // S - mP = xrP
G1 B1, B2, T;
G1::mul(B1, P1, d);
G1::mul(B2, P2, d);
G1::mul(T, A1, h);
B1 -= T;
G1::mul(T, A2, h);
B2 -= T;
Fr h2;
local::Hash hash;
hash << P2 << A1 << A2 << B1 << B2;
hash.get(h2);
return h == h2;
}
bool verify(const CipherTextG2& c, const ZkpBin& zkp) const
{
const MulG<G2> yQmul(yQ_);
@ -1599,6 +1748,7 @@ public:
friend class PublicKey;
friend class PrecomputedPublicKey;
friend class CipherTextA;
friend struct AuxiliaryForZkpDecGT;
template<class T>
friend struct PublicKeyMethod;
public:
@ -1809,7 +1959,14 @@ public:
template<class InputStream>
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
cybozu::writeChar(pb, isMultiplied_ ? '0' : '1', is); if (!*pb) return;
char c;
if (!cybozu::readChar(&c, is)) return;
if (c == '0' || c == '1') {
isMultiplied_ = c == '0';
} else {
*pb = false;
return;
}
if (isMultiplied()) {
m_.load(pb, is, ioMode);
} else {
@ -1819,14 +1976,7 @@ public:
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
char c;
if (!cybozu::readChar(&c, os)) return;
if (c == '0' || c == '1') {
isMultiplied_ = c == '0';
} else {
*pb = false;
return;
}
cybozu::writeChar(pb, os, isMultiplied_ ? '0' : '1'); if (!*pb) return;
if (isMultiplied()) {
m_.save(pb, os, ioMode);
} else {
@ -1895,6 +2045,9 @@ typedef SHE::CipherText CipherText;
typedef SHE::ZkpBin ZkpBin;
typedef SHE::ZkpEq ZkpEq;
typedef SHE::ZkpBinEq ZkpBinEq;
typedef SHE::ZkpDec ZkpDec;
typedef SHE::AuxiliaryForZkpDecGT AuxiliaryForZkpDecGT;
typedef SHE::ZkpDecGT ZkpDecGT;
inline void init(const mcl::CurveParam& cp = mcl::BN254, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
{

@ -17,8 +17,21 @@
namespace mcl { namespace fp {
// some environments do not have utility
template<class T>
T abs_(T x) { return x < 0 ? -x : x; }
inline uint32_t abs_(int32_t x)
{
if (x >= 0) return uint32_t(x);
// avoid undefined behavior
if (x == -2147483647 - 1) return 2147483648u;
return uint32_t(-x);
}
inline uint64_t abs_(int64_t x)
{
if (x >= 0) return uint64_t(x);
// avoid undefined behavior
if (x == -9223372036854775807ll - 1) return 9223372036854775808ull;
return uint64_t(-x);
}
template<class T>
T min_(T x, T y) { return x < y ? x : y; }
@ -157,7 +170,6 @@ void maskArray(T *x, size_t n, size_t bitSize)
template<class T>
size_t getNonZeroArraySize(const T *x, size_t n)
{
assert(n > 0);
while (n > 0) {
if (x[n - 1]) return n;
n--;
@ -165,6 +177,62 @@ size_t getNonZeroArraySize(const T *x, size_t n)
return 1;
}
template<class T>
class BitIterator {
const T *x_;
size_t bitPos_;
size_t bitSize_;
static const size_t TbitSize = sizeof(T) * 8;
public:
BitIterator(const T *x, size_t n)
: x_(x)
, bitPos_(0)
{
assert(n > 0);
n = getNonZeroArraySize(x, n);
if (n == 1 && x[0] == 0) {
bitSize_ = 1;
} else {
assert(x_[n - 1]);
bitSize_ = (n - 1) * sizeof(T) * 8 + 1 + cybozu::bsr<T>(x_[n - 1]);
}
}
bool hasNext() const { return bitPos_ < bitSize_; }
T getNext(size_t w)
{
assert(0 < w && w <= TbitSize);
assert(hasNext());
const size_t q = bitPos_ / TbitSize;
const size_t r = bitPos_ % TbitSize;
const size_t remain = bitSize_ - bitPos_;
if (w > remain) w = remain;
T v = x_[q] >> r;
if (r + w > TbitSize) {
v |= x_[q + 1] << (TbitSize - r);
}
bitPos_ += w;
return v & mask(w);
}
// whethere next bit is 1 or 0 (bitPos is not moved)
bool peekBit() const
{
assert(hasNext());
const size_t q = bitPos_ / TbitSize;
const size_t r = bitPos_ % TbitSize;
return (x_[q] >> r) & 1;
}
void skipBit()
{
assert(hasNext());
bitPos_++;
}
T mask(size_t w) const
{
assert(w <= TbitSize);
return (w == TbitSize ? T(0) : (T(1) << w)) - 1;
}
};
/*
@param out [inout] : set element of G ; out = x^y[]
@param x [in]
@ -231,7 +299,7 @@ void powGeneric(G& out, const G& x, const T *y, size_t n, const Mul& mul, const
out = x;
}
for (int i = (int)n - 1; i >= 0; i--) {
T v = y[i];
v = y[i];
for (int j = m - 2; j >= 0; j -= 2) {
sqr(out, out);
sqr(out, out);
@ -272,6 +340,8 @@ bool mulSmallUnit(T& z, const T& x, U y)
case 8: T::add(z, x, x); T::add(z, z, z); T::add(z, z, z); break;
case 9: { T t; T::add(t, x, x); T::add(t, t, t); T::add(t, t, t); T::add(z, t, x); break; }
case 10: { T t; T::add(t, x, x); T::add(t, t, t); T::add(t, t, x); T::add(z, t, t); break; }
case 11: { T t; T::add(t, x, x); T::add(t, t, x); T::add(t, t, t); T::add(t, t, t); T::sub(z, t, x); break; }
case 12: { T t; T::add(t, x, x); T::add(t, t, t); T::add(z, t, t); T::add(z, z, t); break; }
default:
return false;
}

@ -11,6 +11,7 @@
#ifndef CYBOZU_DONT_USE_STRING
#include <iostream>
#endif
#include <mcl/config.hpp>
#include <mcl/array.hpp>
#include <mcl/util.hpp>
#include <mcl/randgen.hpp>
@ -24,23 +25,11 @@
#error "define MCL_MAX_BIT_SZIE"
#endif
#ifndef MCL_SIZEOF_UNIT
#if defined(CYBOZU_OS_BIT) && (CYBOZU_OS_BIT == 32)
#define MCL_SIZEOF_UNIT 4
#else
#define MCL_SIZEOF_UNIT 8
#endif
#endif
namespace mcl {
namespace vint {
#if MCL_SIZEOF_UNIT == 8
typedef uint64_t Unit;
#else
typedef uint32_t Unit;
#endif
typedef fp::Unit Unit;
template<size_t x>
struct RoundUp {
@ -90,35 +79,19 @@ inline uint32_t mulUnit(uint32_t *pH, uint32_t x, uint32_t y)
inline uint64_t mulUnit(uint64_t *pH, uint64_t x, uint64_t y)
{
#ifdef MCL_VINT_64BIT_PORTABLE
uint32_t a = uint32_t(x >> 32);
uint32_t b = uint32_t(x);
uint32_t c = uint32_t(y >> 32);
uint32_t d = uint32_t(y);
uint64_t ad = uint64_t(d) * a;
uint64_t bd = uint64_t(d) * b;
uint64_t L = uint32_t(bd);
ad += bd >> 32; // [ad:L]
uint64_t ac = uint64_t(c) * a;
uint64_t bc = uint64_t(c) * b;
uint64_t H = uint32_t(bc);
ac += bc >> 32; // [ac:H]
/*
adL
acH
*/
uint64_t t = (ac << 32) | H;
ac >>= 32;
H = t + ad;
if (H < t) {
ac++;
}
/*
ac:H:L
*/
const uint64_t mask = 0xffffffff;
uint64_t v = (x & mask) * (y & mask);
uint64_t L = uint32_t(v);
uint64_t H = v >> 32;
uint64_t ad = (x & mask) * uint32_t(y >> 32);
uint64_t bc = uint32_t(x >> 32) * (y & mask);
H += uint32_t(ad);
H += uint32_t(bc);
L |= H << 32;
H = (ac << 32) | uint32_t(H >> 32);
H >>= 32;
H += ad >> 32;
H += bc >> 32;
H += (x >> 32) * (y >> 32);
*pH = H;
return L;
#elif defined(_WIN64) && !defined(__INTEL_COMPILER)
@ -142,6 +115,7 @@ void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn);
*/
inline uint32_t divUnit(uint32_t *pr, uint32_t H, uint32_t L, uint32_t y)
{
assert(y != 0);
uint64_t t = make64(H, L);
uint32_t q = uint32_t(t / y);
*pr = uint32_t(t % y);
@ -150,7 +124,8 @@ inline uint32_t divUnit(uint32_t *pr, uint32_t H, uint32_t L, uint32_t y)
#if MCL_SIZEOF_UNIT == 8
inline uint64_t divUnit(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y)
{
#if defined(MCL_VINT_64BIT_PORTABLE)
assert(y != 0);
#if defined(MCL_VINT_64BIT_PORTABLE) || (defined(_MSC_VER) && _MSC_VER < 1920)
uint32_t px[4] = { uint32_t(L), uint32_t(L >> 32), uint32_t(H), uint32_t(H >> 32) };
uint32_t py[2] = { uint32_t(y), uint32_t(y >> 32) };
size_t xn = 4;
@ -162,7 +137,7 @@ inline uint64_t divUnit(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y)
*pr = make64(r[1], r[0]);
return make64(q[1], q[0]);
#elif defined(_MSC_VER)
#error "divUnit for uint64_t is not supported"
return _udiv128(H, L, y, pr);
#else
typedef __attribute__((mode(TI))) unsigned int uint128;
uint128 t = (uint128(H) << 64) | L;
@ -213,14 +188,11 @@ T addN(T *z, const T *x, const T *y, size_t n)
T c = 0;
for (size_t i = 0; i < n; i++) {
T xc = x[i] + c;
if (xc < c) {
// x[i] = Unit(-1) and c = 1
z[i] = y[i];
} else {
xc += y[i];
c = y[i] > xc ? 1 : 0;
z[i] = xc;
}
c = xc < c;
T yi = y[i];
xc += yi;
c += xc < yi;
z[i] = xc;
}
return c;
}
@ -301,14 +273,12 @@ T subN(T *z, const T *x, const T *y, size_t n)
assert(n > 0);
T c = 0;
for (size_t i = 0; i < n; i++) {
T yc = y[i] + c;
if (yc < c) {
// y[i] = T(-1) and c = 1
z[i] = x[i];
} else {
c = x[i] < yc ? 1 : 0;
z[i] = x[i] - yc;
}
T yi = y[i];
yi += c;
c = yi < c;
T xi = x[i];
c += xi < yi;
z[i] = xi - yi;
}
return c;
}
@ -552,15 +522,6 @@ size_t getRealSize(const T *x, size_t xn)
return 1;
}
template<class T>
size_t getBitSize(const T *x, size_t n)
{
if (n == 1 && x[0] == 0) return 1;
T v = x[n - 1];
assert(v);
return (n - 1) * sizeof(T) * 8 + 1 + cybozu::bsr<Unit>(v);
}
/*
q[qn] = x[xn] / y[yn] ; qn == xn - yn + 1 if xn >= yn if q
r[rn] = x[xn] % y[yn] ; rn = yn before getRealSize
@ -1204,7 +1165,7 @@ public:
}
/*
set positive value
@note assume little endian system
@note x is treated as a little endian
*/
template<class S>
void setArray(bool *pb, const S *x, size_t size)
@ -1218,15 +1179,9 @@ public:
size_t unitSize = (sizeof(S) * size + sizeof(Unit) - 1) / sizeof(Unit);
buf_.alloc(pb, unitSize);
if (!*pb) return;
char *dst = (char *)&buf_[0];
const char *src = (const char *)x;
size_t i = 0;
for (; i < sizeof(S) * size; i++) {
dst[i] = src[i];
}
for (; i < sizeof(Unit) * unitSize; i++) {
dst[i] = 0;
}
bool b = fp::convertArrayAsLE(&buf_[0], unitSize, x, size);
assert(b);
(void)b;
trim(unitSize);
}
/*
@ -1510,9 +1465,10 @@ public:
*/
static void divMod(VintT *q, VintT& r, const VintT& x, const VintT& y)
{
bool qsign = x.isNeg_ ^ y.isNeg_;
bool xNeg = x.isNeg_;
bool qsign = xNeg ^ y.isNeg_;
udiv(q, r, x.buf_, x.size(), y.buf_, y.size());
r.isNeg_ = x.isNeg_;
r.isNeg_ = xNeg;
if (q) q->isNeg_ = qsign;
}
static void div(VintT& q, const VintT& x, const VintT& y)
@ -1563,10 +1519,12 @@ public:
*/
static void quotRem(VintT *q, VintT& r, const VintT& x, const VintT& y)
{
assert(q != &r);
VintT yy = y;
bool qsign = x.isNeg_ ^ y.isNeg_;
bool yNeg = y.isNeg_;
bool qsign = x.isNeg_ ^ yNeg;
udiv(q, r, x.buf_, x.size(), y.buf_, y.size());
r.isNeg_ = y.isNeg_;
r.isNeg_ = yNeg;
if (q) q->isNeg_ = qsign;
if (!r.isZero() && qsign) {
if (q) {
@ -1755,6 +1713,46 @@ public:
static void invMod(VintT& y, const VintT& x, const VintT& m)
{
assert(!x.isZero() && !m.isZero());
#if 0
VintT u = x;
VintT v = m;
VintT x1 = 1, x2 = 0;
VintT t;
while (u != 1 && v != 1) {
while (u.isEven()) {
u >>= 1;
if (x1.isOdd()) {
x1 += m;
}
x1 >>= 1;
}
while (v.isEven()) {
v >>= 1;
if (x2.isOdd()) {
x2 += m;
}
x2 >>= 1;
}
if (u >= v) {
u -= v;
x1 -= x2;
if (x1 < 0) {
x1 += m;
}
} else {
v -= u;
x2 -= x1;
if (x2 < 0) {
x2 += m;
}
}
}
if (u == 1) {
y = x1;
} else {
y = x2;
}
#else
if (x == 1) {
y = 1;
return;
@ -1787,6 +1785,7 @@ public:
}
b -= a * q;
}
#endif
}
/*
Miller-Rabin

@ -23,35 +23,33 @@ struct ArrayIterator {
, bitSize(bitSize)
, w(w)
, pos(0)
, mask((w == TbitSize ? 0 : (T(1) << w)) - 1)
, mask(makeMask(w))
{
assert(w <= TbitSize);
}
T makeMask(size_t w) const
{
return (w == TbitSize) ? ~T(0) : (T(1) << w) - 1;
}
bool hasNext() const { return bitSize > 0; }
T getNext()
{
if (w == TbitSize) {
bitSize -= w;
return *x++;
if (bitSize < w) {
w = bitSize;
mask = makeMask(w);
}
if (pos + w < TbitSize) {
T v = (*x >> pos) & mask;
pos += w;
if (bitSize < w) {
bitSize = 0;
if (pos + w <= TbitSize) {
T v = x[0] >> pos;
if (pos + w < TbitSize) {
pos += w;
v &= mask;
} else {
bitSize -= w;
pos = 0;
x++;
}
bitSize -= w;
return v;
}
if (pos + bitSize <= TbitSize) {
assert(bitSize <= w);
T v = *x >> pos;
assert((v >> bitSize) == 0);
bitSize = 0;
return v & mask;
}
assert(pos > 0);
T v = (x[0] >> pos) | (x[1] << (TbitSize - pos));
v &= mask;
pos = (pos + w) - TbitSize;

@ -0,0 +1,6 @@
all: low_test
CFLAGS=-I ../include/ -m32 -Ofast -Wall -Wextra -DNDEBUG
low_test: low_test.cpp ../src/low_func_wasm.hpp
$(CXX) -o low_test low_test.cpp $(CFLAGS)

@ -0,0 +1,234 @@
#include <stdio.h>
#include <stdint.h>
void dump(const char *msg, const uint32_t *x, size_t n)
{
printf("%s", msg);
for (size_t i = 0; i < n; i++) {
printf("%08x", x[n - 1 - i]);
}
printf("\n");
}
#include "../src/low_func_wasm.hpp"
#define MCL_USE_VINT
#define MCL_VINT_FIXED_BUFFER
#define MCL_SIZEOF_UNIT 4
#define MCL_MAX_BIT_SIZE 768
#include <mcl/vint.hpp>
#include <cybozu/test.hpp>
#include <cybozu/xorshift.hpp>
#include <cybozu/benchmark.hpp>
#include <mcl/util.hpp>
const int C = 10000;
template<class RG>
void setRand(uint32_t *x, size_t n, RG& rg)
{
for (size_t i = 0; i < n; i++) {
x[i] = rg.get32();
}
}
/*
g++ -Ofast -DNDEBUG -Wall -Wextra -m32 -I ./include/ misc/low_test.cpp
Core i7-8700
mulT karatsuba
N = 6, 182clk 225clk
N = 8, 300clk 350clk
N = 12, 594clk 730clk
*/
template<size_t N>
void mulTest()
{
printf("N=%zd (%zdbit)\n", N, N * 32);
cybozu::XorShift rg;
uint32_t x[N];
uint32_t y[N];
uint32_t z[N * 2];
for (size_t i = 0; i < 1000; i++) {
setRand(x, N, rg);
setRand(y, N, rg);
// remove MSB
x[N - 1] &= 0x7fffffff;
y[N - 1] &= 0x7fffffff;
mcl::Vint vx, vy;
vx.setArray(x, N);
vy.setArray(y, N);
vx *= vy;
mcl::mulT<N>(z, x, y);
CYBOZU_TEST_EQUAL_ARRAY(z, vx.getUnit(), N * 2);
memset(z, 0, sizeof(z));
mcl::karatsubaT<N>(z, x, y);
CYBOZU_TEST_EQUAL_ARRAY(z, vx.getUnit(), N * 2);
}
CYBOZU_BENCH_C("mulT", C, mcl::mulT<N>, z, x, y);
CYBOZU_BENCH_C("kara", C, mcl::karatsubaT<N>, z, x, y);
}
CYBOZU_TEST_AUTO(mulT)
{
mulTest<8>();
mulTest<12>();
}
template<size_t N>
void sqrTest()
{
printf("N=%zd (%zdbit)\n", N, N * 32);
cybozu::XorShift rg;
uint32_t x[N];
uint32_t y[N * 2];
for (size_t i = 0; i < 1000; i++) {
setRand(x, N, rg);
// remove MSB
x[N - 1] &= 0x7fffffff;
mcl::Vint vx;
vx.setArray(x, N);
vx *= vx;
mcl::sqrT<N>(y, x);
CYBOZU_TEST_EQUAL_ARRAY(y, vx.getUnit(), N * 2);
}
CYBOZU_BENCH_C("sqrT", C, mcl::sqrT<N>, y, x);
}
CYBOZU_TEST_AUTO(sqrT)
{
sqrTest<8>();
sqrTest<12>();
}
struct Montgomery {
mcl::Vint p_;
mcl::Vint R_; // (1 << (pn_ * 64)) % p
mcl::Vint RR_; // (R * R) % p
uint32_t rp_; // rp * p = -1 mod M = 1 << 64
size_t pn_;
Montgomery() {}
explicit Montgomery(const mcl::Vint& p)
{
p_ = p;
rp_ = mcl::fp::getMontgomeryCoeff(p.getUnit()[0]);
pn_ = p.getUnitSize();
R_ = 1;
R_ = (R_ << (pn_ * 64)) % p_;
RR_ = (R_ * R_) % p_;
}
void toMont(mcl::Vint& x) const { mul(x, x, RR_); }
void fromMont(mcl::Vint& x) const { mul(x, x, 1); }
void mul(mcl::Vint& z, const mcl::Vint& x, const mcl::Vint& y) const
{
const size_t ySize = y.getUnitSize();
mcl::Vint c = x * y.getUnit()[0];
uint32_t q = c.getUnit()[0] * rp_;
c += p_ * q;
c >>= sizeof(uint32_t) * 8;
for (size_t i = 1; i < pn_; i++) {
if (i < ySize) {
c += x * y.getUnit()[i];
}
uint32_t q = c.getUnit()[0] * rp_;
c += p_ * q;
c >>= sizeof(uint32_t) * 8;
}
if (c >= p_) {
c -= p_;
}
z = c;
}
void mod(mcl::Vint& z, const mcl::Vint& xy) const
{
z = xy;
for (size_t i = 0; i < pn_; i++) {
uint32_t q = z.getUnit()[0] * rp_;
mcl::Vint t = q;
z += p_ * t;
z >>= 32;
}
if (z >= p_) {
z -= p_;
}
}
};
template<size_t N>
void mulMontTest(const char *pStr)
{
mcl::Vint vp;
vp.setStr(pStr);
Montgomery mont(vp);
cybozu::XorShift rg;
uint32_t x[N];
uint32_t y[N];
uint32_t z[N];
uint32_t _p[N + 1];
uint32_t *const p = _p + 1;
vp.getArray(p, N);
p[-1] = mont.rp_;
for (size_t i = 0; i < 1000; i++) {
setRand(x, N, rg);
setRand(y, N, rg);
// remove MSB
x[N - 1] &= 0x7fffffff;
y[N - 1] &= 0x7fffffff;
mcl::Vint vx, vy, vz;
vx.setArray(x, N);
vy.setArray(y, N);
mont.mul(vz, vx, vy);
mcl::mulMontT<N>(z, x, y, p);
CYBOZU_TEST_EQUAL_ARRAY(z, vz.getUnit(), N);
mont.mul(vz, vx, vx);
mcl::sqrMontT<N>(z, x, p);
CYBOZU_TEST_EQUAL_ARRAY(z, vz.getUnit(), N);
}
CYBOZU_BENCH_C("mulMontT", C, mcl::mulMontT<N>, x, x, y, p);
CYBOZU_BENCH_C("sqrMontT", C, mcl::sqrMontT<N>, x, x, p);
}
template<size_t N>
void modTest(const char *pStr)
{
mcl::Vint vp;
vp.setStr(pStr);
Montgomery mont(vp);
cybozu::XorShift rg;
uint32_t xy[N * 2];
uint32_t z[N];
uint32_t _p[N + 1];
uint32_t *const p = _p + 1;
vp.getArray(p, N);
p[-1] = mont.rp_;
for (size_t i = 0; i < 1000; i++) {
setRand(xy, N * 2, rg);
// remove MSB
xy[N * 2 - 1] &= 0x7fffffff;
mcl::Vint vxy, vz;
vxy.setArray(xy, N * 2);
mont.mod(vz, vxy);
mcl::modT<N>(z, xy, p);
CYBOZU_TEST_EQUAL_ARRAY(z, vz.getUnit(), N);
}
CYBOZU_BENCH_C("modT", C, mcl::modT<N>, z, xy, p);
}
CYBOZU_TEST_AUTO(mont)
{
const char *pBN254 = "0x2523648240000001ba344d80000000086121000000000013a700000000000013";
puts("BN254");
mulMontTest<8>(pBN254);
modTest<8>(pBN254);
const char *pBLS12_381 = "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab";
puts("BLS12");
mulMontTest<12>(pBLS12_381);
modTest<12>(pBLS12_381);
}

@ -0,0 +1,119 @@
P ; generator
x ; secret key
xP ; public key
Enc(m;r) = (mP + rxP, rP)
c = (S, T)
dec(c) := S - xT
dec(Enc(m;r)) = (mP + rxP) - x(rP) = mP
DLP(mP) := m
Dec(c) := DLP(dec(c))
ZKP of dec(c) = m
z := Enc(m;0) = (mP, 0)
c - z = (rxP, rP) ; r is unknown
ZKP of dec(c - z) = 0
(P1, P2) := (P, rP)
(A1, A2) := (xP, xrP)
Prover shows that x(P1, P2) = (A1, A2) without revealing x.
b ; rand
B = (b P1, b P2)
h = Hash(P2, A1, A2, B1, B2)
d = b + h a
pi = (d, h)
Verifier
Bi := d Pi - h Ai
verify h = Hash(P2, A1, A2, B1, B2)
-----------------------------------------------------------------------------
CipherTextGT
P ; generator of GT, GT=<P>
x1, x2 ; secrect key
(P0, P1, P2, P3) := (P, x1 P, x2 P, x1 x2 P) ; public information
CipherText c = (A0, A1, A2, A3)
dec(c) = 0 <=> A0 = x2 A1 + x1 A2 - x1 x2 A3 ; (*)
F(a1, a2, a3) := a2 A1 + a1 A2 - a3 A3
dec(c) = 0 <=> A0 = F(x1, x2, x1 x2)
Sigma-protocol for dec(c) = 0, i.e., show (*)
Prover:
b1, b2, b3 ; rand
Bi := bi P (i = 1, 2, 3)
X := F(b1, b2, b3)
send (B1, B2, B3, X) to Verfier
Verifier:
takes h randomly and send to Prover
Prover:
d1 := b1 + h x1
d2 := b2 + h x2
d3 := b3 + h x1 x2
send (d1, d2, d3) to Verifier
Verifier:
verify
di P = Bi + h Pi (i = 1, 2, 3)
X = F(d1, d2, d3) - h A0
and accept it
Fiat-Shamir transform:
Prover:
b1, b2, b3 ; random value
Bi := bi P (i = 1, 2, 3)
X := F(b1, b2, b3)
h := Hash(P0, ..., P3, A0, ..., A3, B1, B2, B3, X)
d1 := b1 + h x1
d2 := b2 + h x2
d3 := b3 + h x1 x2
pi := (d1, d2, d3, h)
Verifier:
(pi, {Pi}, {Ai}) given
Bi' := di P - h Pi for i = 1, 2, 3
X' := F(d1, d2, d3) - h A0
verify Hash({Pi}, {Ai}, {Bi'}, X') = h
Completeness
B1' = d1 P - h P1 = (b1 + h x1) P - h x1 P = b1 P = B1
B2' = d2 P - h P2 = (b2 + h x2) P - h x2 P = b2 P = B2
B3' = d3 P - h P3 = (b3 + h x1 x2) P - h x1 x2 P = B3
X' = F(b1 + h x1, b2 + h x2, b3 + h x1 x2) - h A0
= F(b1, b2, b3) + h F(x1, x2, x1 x2) - h A0
= F(b1, b2, b3) + h (F(x1, x2, x1 x2) - A0)
= F(b1, b2, b3) = X
OK
Soundness
{Ai}, pi=(d1, d2, d3, h) ; given
compute Bi', X' as above
Suppose Hash({Pi}, {Ai}, {Bi'}, X') = h
define
b1 := d1 - h x1
b2 := d2 - h x2
b3 := d3 - h x1 x2
where x1, x2 are unknown
d1, d2, d3 are free parameters, so b1, b2, b3 are also free.
B1' = d1 P - h P1 = b1 P
B2' = b2 P
B3' = b3 P
Y := F(x1, x2, x1 x2) - A0; unknown, but it is fixed
X' = F(d1, d2, d3) - h A0 = F(b1 + h x1, b2 + h x2, b3 + h x1 x2) - h A0
= F(b1, b2, b3) + h(F(x1, x2, x1 x2) - A0)
= F(b1, b2, b3) + h Y
Hash({Pi}, {Ai}, b1 P, b2 P, b3 P, F(b1, b2, b3) + h Y) = h
To found {b1, b2, b3, h} to hold this equation, Y must be 0.

@ -250,7 +250,7 @@ PrecomputedPublicKeyはPublicKeyの高速版
* `CT she.sub(CT x, CT y)`(JS)
* 暗号文xから暗号文yを引いてzにセットする(またはその値を返す)
* `void CT::neg(CT& y, const CT& x)`(C++)
* `void she.neg(CT x)`(JS)
* `CT she.neg(CT x)`(JS)
* 暗号文xの符号反転をyにセットする(またはその値を返す)
* `void CT::mul(CT& z, const CT& x, int y)`(C++)
* `CT she.mulInt(CT x, int y)`(JS)
@ -275,7 +275,9 @@ PrecomputedPublicKeyはPublicKeyの高速版
* ZkpBinEq 暗号文encG1(m1), encG2(m2)についてm1 = m2 = 0または1であることを検証できる
### API
PK = PublicKey or PrecomputedPublicKey
- SK = SecretKey
- PK = PublicKey or PrecomputedPublicKey
- AUX = AuxiliaryForZkpDecGT
* `void PK::encWithZkpBin(CipherTextG1& c, Zkp& zkp, int m) const`(C++)
* `void PK::encWithZkpBin(CipherTextG2& c, Zkp& zkp, int m) const`(C++)
@ -290,6 +292,14 @@ PK = PublicKey or PrecomputedPublicKey
* `[CipherTextG1, CipherTextG2, ZkpEqBin] PK::encWithZkpBinEq(m)`(JS)
* m(=0 or 1)を暗号化して暗号文c1, c2とゼロ知識証明zkpをセットする(または[c1, c2, zkp]を返す)
* mが0でも1でもなければ例外
* `SK::decWithZkp(DecZkpDec& zkp, const CipherTextG1& c, const PublicKey& pub) const`(C++)
* `[m, ZkpDecG1] SK::decWithZkpDec(c, pub)`(JS)
* CipherTextG1暗号文`c`を復号して`m`と`zkp`を返す. `zkp`は`dec(c) = m`の証明
* `pub`は計算コストを減らすために利用する
* `SK::decWithZkpDec(ZkpDecGT& zkp, const CipherTextGT& c, const AuxiliaryForZkpDecGT& aux) const`(C++)
* `[m, ZkpDecGT] SK::decWithZkpDecGT(c, aux)`(JS)
* CipherTextGT暗号文`c`を復号して`m`と`zkp`を返す. `zkp`は`dec(c) = m`の証明
* `aux = pub.getAuxiliaryForZkpDecGT()`. auxは計算コストを減らすために利用する
## グローバル関数

@ -1,6 +1,6 @@
# she ; Two-level homomorphic encryption library for browser/Node.js by WebAssembly
# Abstruct
# Abstract
she is a somewhat(two-level) homomorphic encryption library,
which is based on pairings.
This library supports polynomially many homomorphic additions and
@ -31,7 +31,7 @@ Sum_i Enc(x_i) Enc(y_i) = Enc(Sum_i x_i y_i).
* decrypt a ciphertext with a secret key
## Homomorphic operations
* homomorphic addtion/substraction over ciphertexts of the same ciphertext class
* homomorphic addition/subtraction over ciphertexts of the same ciphertext class
* homomprphic multiplication over ciphertext of CipherTextG1 and CipherTextG2
* The class of the result is CipherTextGT.
@ -39,7 +39,7 @@ Sum_i Enc(x_i) Enc(y_i) = Enc(Sum_i x_i y_i).
* This library requires to solve a small DLP to decrypt a ciphertext.
* The decryption timing is O(m/s), where s is the size of table to solve DLP, and m is the size fo a plaintext.
* call `setRangeForDLP(s)` to set the table size.
* The maximun `m/s` is set by `setTryNum(tryNum)`.
* The maximum `m/s` is set by `setTryNum(tryNum)`.
## Zero-knowledge proof class
* A zero-knowledge proof is simultaneously created when encrypting a plaintext `m`.
@ -66,7 +66,7 @@ and read `she.js`.
## A sample for JS
```
```js
// initialize a library
she.init().then(() => {
const sec = new she.SecretKey()
@ -103,7 +103,7 @@ she.init().then(() => {
# A sample for C++
How to build the library, see [mcl](https://github.com/herumi/mcl/#installation-requirements).
```
```c++
#include <mcl/she.hpp>
int main()
try
@ -255,7 +255,7 @@ PK means PublicKey or PrecomputedPublicKey
* `CT she.sub(CT x, CT y)`(JS)
* subtract `x` and `y` and set the value to `z`(or return the value)
* `void CT::neg(CT& y, const CT& x)`(C++)
* `void she.neg(CT x)`(JS)
* `CT she.neg(CT x)`(JS)
* negate `x` and set the value to `y`(or return the value)
* `void CT::mul(CT& z, const CT& x, int y)`(C++)
* `CT she.mulInt(CT x, int y)`(JS)
@ -281,7 +281,9 @@ PK means PublicKey or PrecomputedPublicKey
* ZkpBinEq ; verify whether `m1 = m2 = 0` or `1` for ciphertexts `encG1(m1)` and `encG2(m2)`
### API
PK = PublicKey or PrecomputedPublicKey
- SK = SecretKey
- PK = PublicKey or PrecomputedPublicKey
- AUX = AuxiliaryForZkpDecGT
* `void PK::encWithZkpBin(CipherTextG1& c, Zkp& zkp, int m) const`(C++)
* `void PK::encWithZkpBin(CipherTextG2& c, Zkp& zkp, int m) const`(C++)
@ -296,6 +298,14 @@ PK = PublicKey or PrecomputedPublicKey
* `[CipherTextG1, CipherTextG2, ZkpEqBin] PK::encWithZkpBinEq(m)`(JS)
* encrypt `m`(=0 or 1) and set ciphertexts `c1`, `c2` and zero-knowledge proof `zkp`(or returns [c1, c2, zkp])
* throw exception if m != 0 and m != 1
* `SK::decWithZkp(DecZkpDec& zkp, const CipherTextG1& c, const PublicKey& pub) const`(C++)
* `[m, ZkpDecG1] SK::decWithZkpDec(c, pub)`(JS)
* decrypt CipherTextG1 `c` and get `m` and zkp, which proves that `dec(c) = m`.
* `pub` is used for reducing some computation.
* `SK::decWithZkpDec(ZkpDecGT& zkp, const CipherTextGT& c, const AuxiliaryForZkpDecGT& aux) const`(C++)
* `[m, ZkpDecGT] SK::decWithZkpDecGT(c, aux)`(JS)
* decrypt CipherTextGT `c` and get `m` and zkp, which proves that `dec(c) = m`.
* `aux = pub.getAuxiliaryForZkpDecGT()`, which is used for reducing some computation.
## Global functions

@ -0,0 +1,18 @@
p=21888242871839275222246405745257275088696311157297823662689037894645226208583
print("over 253 bit")
for i in range (10):
print(i, (p * i) >> 253)
def maxarg(x):
return x // p
print("maxarg")
for i in range(16):
print(i, maxarg(i << 253))
x=0x2c130429c1d4802eb8703197d038ebd5109f96aee333bd027963094f5bb33ad
y = x * 9
print(hex(y))

@ -8,6 +8,10 @@ if "%1"=="dll" (
rem nasm -f win64 -D_WIN64 src\asm\low_x86-64.asm
rem lib /OUT:lib\mcl.lib /nodefaultlib fp.obj src\asm\low_x86-64.obj
if "%1"=="dll" (
set CFLAGS=%CFLAGS% /DMCL_NO_AUTOLINK /DMCLBN_NO_AUTOLINK
)
echo cl /c %CFLAGS% src\fp.cpp /Foobj\fp.obj
cl /c %CFLAGS% src\fp.cpp /Foobj\fp.obj
echo lib /nologo /OUT:lib\mcl.lib /nodefaultlib obj\fp.obj
@ -15,22 +19,17 @@ echo lib /nologo /OUT:lib\mcl.lib /nodefaultlib obj\fp.obj
if "%1"=="dll" (
echo cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj
cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj /DMCLBN_NO_AUTOLINK
cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj
echo link /nologo /DLL /OUT:bin\mclbn256.dll obj\bn_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn256.lib
link /nologo /DLL /OUT:bin\mclbn256.dll obj\bn_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn256.lib
echo cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj
cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj /DMCLBN_NO_AUTOLINK
echo link /nologo /DLL /OUT:bin\mclbn384.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.lib
link /nologo /DLL /OUT:bin\mclbn384.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.lib
echo cl /c %CFLAGS% src\she_c256.cpp /Foobj\she_c256.obj /DMCLBN_NO_AUTOLINK
cl /c %CFLAGS% src\she_c256.cpp /Foobj\she_c256.obj /DMCLBN_NO_AUTOLINK
echo link /nologo /DLL /OUT:bin\mclshe256.dll obj\she_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c256.lib
link /nologo /DLL /OUT:bin\mclshe256.dll obj\she_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c256.lib
echo cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
echo link /nologo /DLL /OUT:bin\mclbn384_256.dll obj\bn_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384_256.lib
link /nologo /DLL /OUT:bin\mclbn384_256.dll obj\bn_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384_256.lib
echo cl /c %CFLAGS% src\she_c384_256.cpp /Foobj\she_c384_256.obj /DMCLBN_NO_AUTOLINK
cl /c %CFLAGS% src\she_c384_256.cpp /Foobj\she_c384_256.obj /DMCLBN_NO_AUTOLINK
echo cl /c %CFLAGS% src\she_c384_256.cpp /Foobj\she_c384_256.obj /DMCL_NO_AUTOLINK
cl /c %CFLAGS% src\she_c384_256.cpp /Foobj\she_c384_256.obj /DMCL_NO_AUTOLINK
echo link /nologo /DLL /OUT:bin\mclshe384_256.dll obj\she_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c384_256.lib
link /nologo /DLL /OUT:bin\mclshe384_256.dll obj\she_c384_256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe_c384_256.lib
) else (
@ -38,7 +37,7 @@ if "%1"=="dll" (
cl /c %CFLAGS% src\bn_c256.cpp /Foobj\bn_c256.obj
lib /nologo /OUT:lib\mclbn256.lib /nodefaultlib obj\bn_c256.obj lib\mcl.lib
echo cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj
cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj
lib /nologo /OUT:lib\mclbn384.lib /nodefaultlib obj\bn_c384.obj lib\mcl.lib
echo cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
cl /c %CFLAGS% src\bn_c384_256.cpp /Foobj\bn_c384_256.obj
lib /nologo /OUT:lib\mclbn384_256.lib /nodefaultlib obj\bn_c384_256.obj lib\mcl.lib
)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save