herumi / mcl

a portable and fast pairing-based cryptography library
BSD 3-Clause "New" or "Revised" License
450 stars 152 forks source link

Missing docs for c++ interface? #72

Closed earonesty closed 2 years ago

earonesty commented 4 years ago

There are only docs for the C interface. Is that what I should use in a C++ project?

How can I get the bit size for Fr? Is this the right way to create an Fr?

mcl::FpT<mcl::ZnTag, 256> Fr;

Which of these should I use for initializing:

This (seems ok):

Ec P;
mcl::initCurve<Ec, Fr>(MCL_BN381_1, &P);

Or (seems unsafe, cannot use more than 1 curve in an application)

initPairing(mcl::BLS12_381);
G1 P;

How do i get the order and bit-size of Fr/Fp for G1, and G2?

Can I switch between curves in one app? Or is this a big performance hit.

How do i get a 'generator' for G1, and G2? mapToG1(g1, 1) seems ok.

I got everything to work with BLS12_381 (I still thing I am doing some things wrong, lookoing at the getOp().mp instead of higher level stuff to get curve order... but when I use BN254, I get "bad size of register"

herumi commented 4 years ago

Is that what I should use in a C++ project?

I'm sorry for the inadequate documents. I have little time to write it, but I'll do little by little.

Can I switch between curves in one app? Or is this a big performance hit.

What curve parameters do you want to use? Could you tell me what you want? (use pairing, or only elliptic curve?)

The current version does not support multi parameters. At first, I had developed the features, but I gave up it because a class dependency was very complicated.

How can I get the bit size for Fr?

The direct function is not provided. Call mcl::gmp::getBitSize() after converting to mpz_class.

The generator of G1/G2 is not unique, so the api is not provided. mapToG1(P, 1) or hashAndMapToG1(P, "abc", 3). cf. sample/pairing.cpp

#include <mcl/bls12_381.hpp>

using namespace mcl::bn;

int main()
{
    initPairing(mcl::BLS12_381);
    Fr x;
    x.setStr("12345678abcdefadef", 16);
    printf("x=%s bitSize=%zd\n", x.getStr(16).c_str(), mcl::gmp::getBitSize(x.getMpz()));
    x.setByCSPRNG();
    printf("x=%s bitSize=%zd\n", x.getStr(16).c_str(), mcl::gmp::getBitSize(x.getMpz()));

}
earonesty commented 4 years ago

Thank you so much! We are attempting to use this lib (it is faster than most others) for a searchable threshold encryption system.

earonesty commented 4 years ago

Things I learned:

herumi commented 4 years ago

there are multiple threads using different pairing curves that could be dangerous with mcl.

I tried to make a very dirty hack of bn.hpp. I copied bn.hpp to bn2.hpp and renamed the namespace bn to bn2 and comment out according to mapto_wb19.hpp. multi-branch The sample is multi.cpp.

Fr, G1, et al. are plain object data, then you can use them in a union if you call the correct method of each content.

union Fr {
    bn::Fr x;
    bn2::Fr x;
};
herumi commented 4 years ago

But we still get "bad size of register" when init using BN254 for any operations.... even if we turn off all 381 support.

I've seen the error. make bin/bn_test.exe && bin/bn_test.exe runs well? Could you tell me your OS/CPU/compiler and compile option?

And could you build the wrong binary with debug mode (-Og -g3) and

gdb <the binary>
catch throw
run
bt

Then I can know the position of the exception.

herumi commented 4 years ago

Common generator is getG1basePoint for G1, but not G2.

Sorry, the getG1basePoint is NOT for pairing curves. https://github.com/herumi/mcl/blob/master/include/mcl/bn.h#L544-L549

If you need the ETH base point for BLS12_381, then see Set String. For BN254, please select any generator that you want.

herumi commented 4 years ago

ETH mode is === big endian mode. Still can't get it to output 0x02 and 0x03 for the first byte though.

Please see Serialization format of mcl. mcl does not support output 0x02 and 0x03. mcl supports only the compression serialization of ETH.

earonesty commented 4 years ago

yes, bn_test.exe works well, i only have problems when including CMakeLists as a subproject.

make:

g++ -g3 -Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith -m64 -I include -I test -fomit-frame-pointer -DNDEBUG -Ofast -DMCL_DONT_USE_OPENSSL -fPIC -DMCL_USE_LLVM=1 -c src/fp.cpp -o obj/fp.o -MMD -MP -MF obj/fp.d

vs cmake:

g++ -DMCL_USE_LLVM=1 -I/home/erik/kata/cpp/mcl/include -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER -std=c++11 -Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith -O3 -DNDEBUG -march=native -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER -DMCL_DONT_USE_OPENSSL -O3 -DNDEBUG -fPIC -std=gnu++1z -o CMakeFiles/mcl_st.dir/src/fp.cpp.o -c /home/erik/kata/cpp/mcl/src/fp.cpp

maybe it's the O3 vs Ofast? or the -m64 ... not sure. i am trying to make them the same, switched from clang to g++ to be sure. this fails at the very beginning mcl::bn::initPairing(mcl::BN254) during Xbyak::RegExp::RegExp.

The same error occurs with BLS12_381. Haven't figured it out yet.

herumi commented 4 years ago

I want to know the following information:

Does the following command run well? It runs well on Ubuntu 18.04.4 + Core i7-7700 + gcc 7.4(and clang 8.0.1)

cd mcl
g++ -I ./include -std=c++11 -Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith -O3 -DNDEBUG -march=native -DMCL_USE_VINT -DMCL_VINT_FIXED_BUFFER -DMCL_DONT_USE_OPENSSL -O3 -DNDEBUG -fPIC -std=gnu++1z src/fp.cpp sample/pairing.cpp && ./a.out
earonesty commented 4 years ago

OS: ubuntu cpu: (Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz) compiler: g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0

I found the problem! The issue was that I was calling initPairing during static initialization. This worked for BN381_1 but it did not work for BLS12_381.

Important when using mcl/c++: be sure to call initPairing from "main", or your regular entry point... not in static initialization.

I think everything works now...we are doing a searchable encryption system using pairings where you can search and never decrypt.

earonesty commented 4 years ago

Windows 64-bit compile I get "divUnit for uint64_t is not supported".
I modified the CMakeLists: if (WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMCL_VINT_64BIT_PORTABLE")

earonesty commented 4 years ago

I will write a up small help file explaing how to use in C++ (vs api.md which is for c).

Added a pull req to make the windows runtime lib choice optional in the CMakeFile (when using mcl as a cmake component, this was helpful)

herumi commented 4 years ago

Windows 64-bit compile I get "divUnit for uint64_t is not supported".

I fixed it and use _udiv128 if possible at https://github.com/herumi/mcl/commit/a53b6b7f4c6b401029c99ffd3154f5868d868a94

earonesty commented 4 years ago

the _udiv128 commit works well on 64-bit windows, i removed the portable flag, no longer needed