├── .travis.yml ├── Makefile ├── README.md ├── bls ├── Makefile ├── include │ └── bls │ │ └── bls.h └── src │ └── bls_c.cpp ├── bn.nix ├── cybozulib └── include │ └── cybozu │ ├── atoi.hpp │ ├── benchmark.hpp │ ├── bit_operation.hpp │ ├── crypto.hpp │ ├── endian.hpp │ ├── exception.hpp │ ├── hash.hpp │ ├── inttype.hpp │ ├── itoa.hpp │ ├── option.hpp │ ├── random_generator.hpp │ ├── sha2.hpp │ ├── test.hpp │ ├── unordered_map.hpp │ └── xorshift.hpp ├── default.nix ├── license ├── cybozulib │ └── COPYRIGHT ├── mcl │ └── COPYRIGHT ├── readme.md └── xbyak │ └── COPYRIGHT ├── mcl ├── Makefile ├── bin │ └── .emptydir ├── common.mk ├── include │ └── mcl │ │ ├── bn.h │ │ ├── bn.hpp │ │ ├── bn256.hpp │ │ ├── bn384.hpp │ │ ├── bn512.hpp │ │ ├── ec.hpp │ │ ├── ecparam.hpp │ │ ├── fp.hpp │ │ ├── fp_tower.hpp │ │ ├── gmp_util.hpp │ │ ├── lagrange.hpp │ │ ├── op.hpp │ │ ├── operator.hpp │ │ ├── random.hpp │ │ ├── util.hpp │ │ └── vint.hpp ├── lib │ └── .emptydir ├── obj │ └── .emptydir ├── src │ ├── asm │ │ └── .emptydir │ ├── bn_c384.cpp │ ├── bn_c_impl.hpp │ ├── conversion.hpp │ ├── fp.cpp │ ├── fp_generator.hpp │ ├── gen.cpp │ ├── llvm_gen.hpp │ ├── low_func.hpp │ ├── low_func_llvm.hpp │ └── proto.hpp └── test │ ├── bn_c384_test.cpp │ ├── bn_c_test.hpp │ └── bn_test.cpp └── xbyak └── xbyak ├── xbyak.h ├── xbyak_bin2hex.h ├── xbyak_mnemonic.h └── xbyak_util.h /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | install: 3 | - sudo rm -rf /usr/local/clang-3.5.0 4 | - wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - 5 | - sudo apt-add-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-3.8 main" 6 | - sudo apt-get update 7 | - sudo apt-get install llvm-3.8 llvm-3.8-dev clang-3.8 clang-3.8-dev libc++-dev 8 | - sudo ln -sf /usr/bin/clang-3.8 /usr/bin/clang 9 | - sudo ln -sf /usr/bin/llc-3.8 /usr/bin/llc 10 | - sudo ln -sf /usr/bin/opt-3.8 /usr/bin/opt 11 | script: 12 | - make 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | UNAME_S=$(shell uname -s) 2 | ifeq ($(UNAME_S),Darwin) 3 | LIB_SUF=dylib 4 | else 5 | LIB_SUF=so 6 | endif 7 | TARGET=bls/libbls384.$(LIB_SUF) 8 | MCL_LIB=mcl/lib/libmcl.$(LIB_SUF) 9 | TARGET_STATIC=bls/libbls384.a 10 | MCL_LIB_STATIC=mcl/lib/libmcl.a 11 | 12 | all: $(TARGET) $(TARGET_STATIC) 13 | 14 | $(MCL_LIB): 15 | $(MAKE) -C mcl UPDATE_ASM=1 lib/libmcl.$(LIB_SUF) CFLAGS_USER=-std=c++11 MCL_MAX_BIT_SIZE=384 16 | 17 | $(MCL_LIB_STATIC): 18 | $(MAKE) -C mcl UPDATE_ASM=1 lib/libmcl.a CFLAGS_USER=-std=c++11 MCL_MAX_BIT_SIZE=384 19 | 20 | $(TARGET): $(MCL_LIB) 21 | $(MAKE) -C bls libbls384.$(LIB_SUF) MCL_MAX_BIT_SIZE=384 22 | 23 | $(TARGET_STATIC): $(MCL_LIB_STATIC) 24 | $(MAKE) -C bls libbls384.a MCL_MAX_BIT_SIZE=384 25 | 26 | clean: 27 | $(MAKE) -C mcl clean 28 | $(MAKE) -C bls clean 29 | 30 | .PHONY: $(MCL_LIB) $(TARGET) 31 | 32 | PREFIX?=/usr/local 33 | DESTDIR?= 34 | install: $(TARGET) 35 | mkdir -p $(DESTDIR)$(PREFIX)/lib 36 | cp -a $(MCL_LIB) $(DESTDIR)$(PREFIX)/lib 37 | cp -a $(TARGET) $(DESTDIR)$(PREFIX)/lib 38 | cp -a $(MCL_LIB_STATIC) $(DESTDIR)$(PREFIX)/lib 39 | cp -a $(TARGET_STATIC) $(DESTDIR)$(PREFIX)/lib 40 | mkdir -p $(DESTDIR)$(PREFIX)/include/bls 41 | cp -a bls/include/bls/bls.h $(DESTDIR)$(PREFIX)/include/bls 42 | mkdir -p $(DESTDIR)$(PREFIX)/include/mcl 43 | cp -a mcl/include/mcl/bn.h $(DESTDIR)$(PREFIX)/include/mcl 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bn 2 | [![Build Status](https://travis-ci.org/dfinity/bn.svg?branch=master)](https://travis-ci.org/dfinity/bn) 3 | 4 | Barreto-Naehrig curve implementation and BLS 5 | 6 | ## Install 7 | 8 | ### Requirements 9 | 10 | Your system needs have installed first llvm, g++, gmp and openssl{-dev}. On Ubuntu: 11 | 12 | ``` 13 | sudo apt install llvm g++ libgmp-dev libssl-dev 14 | ``` 15 | 16 | ### From source 17 | 18 | To install from source, you can run the following commands: 19 | ```bash 20 | git clone https://github.com/dfinity/bn 21 | cd bn 22 | make 23 | make install 24 | ``` 25 | The library is then installed under `/usr/local/`. 26 | In order to use it as a library for any project (see [go-dfinity-crypto](https://github.com/dfinity/go-dfinity-crypto) for example), your loader must be aware of this location. There are two common solutions: 27 | - To use it for the current session: 28 | ```bash 29 | export LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib 30 | ``` 31 | - To use it permanently, add `/usr/local/lib` to `/etc/ld.so.conf` , then run `ldconfig` as root 32 | 33 | If you wish to change the path where the libraries are installed, you can use: 34 | ```bash 35 | make install PREFIX=/my/custom/path 36 | ``` 37 | 38 | ### From latest release 39 | 40 | Prebuilt libraries are available for select platforms. 41 | * [bn-latest-amd64-apple-darwin16.7.tar.gz](https://s3-us-west-2.amazonaws.com/dfinity/crypto/bn/latest/bn-latest-amd64-apple-darwin16.7.tar.gz) 42 | * [bn-latest-amd64-linux-ubuntu16.04.tar.gz](https://s3-us-west-2.amazonaws.com/dfinity/crypto/bn/latest/bn-latest-amd64-linux-ubuntu16.04.tar.gz) 43 | 44 | You may need to place the libraries in the correct path as explained in the above section. 45 | 46 | ## License 47 | 48 | [**(C) 2017 DFINITY STIFTUNG**](http://dfinity.network) 49 | 50 | All code and designs are open sourced under GPL V3. 51 | 52 | ![image](https://user-images.githubusercontent.com/6457089/32753794-10f4cbc2-c883-11e7-8dcf-ff8088b38f9f.png) 53 | -------------------------------------------------------------------------------- /bls/Makefile: -------------------------------------------------------------------------------- 1 | include ../mcl/common.mk 2 | 3 | CFLAGS += -std=c++11 -I../mcl/include -I./include -DMCL_MAX_BIT_SIZE=384 -L../mcl/lib 4 | 5 | SRC=src/bls_c.cpp 6 | HEADER=include/bls/bls.h 7 | 8 | all: libbls384.$(LIB_SUF) libbls384.a 9 | 10 | libbls384.$(LIB_SUF): $(SRC) $(HEADER) 11 | $(CXX) -o $@ $(SRC) -shared $(CFLAGS) -D"MCLBN_FP_UNIT_SIZE=6" -lmcl -lgmpxx -lgmp -lcrypto 12 | 13 | libbls384.o: $(SRC) $(HEADER) 14 | $(CXX) -o $@ -c $(SRC) $(CFLAGS) -D"MCLBN_FP_UNIT_SIZE=6" 15 | 16 | libbls384.a: libbls384.o ; ar rcs $@ $^ 17 | 18 | clean: 19 | $(RM) libbls384.$(LIB_SUF) 20 | -------------------------------------------------------------------------------- /bls/include/bls/bls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief C interface of bls.hpp 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | 11 | #ifdef _MSC_VER 12 | #ifdef BLS_DLL_EXPORT 13 | #define BLS_DLL_API __declspec(dllexport) 14 | #else 15 | #define BLS_DLL_API __declspec(dllimport) 16 | #ifndef BLS_NO_AUTOLINK 17 | #if MCLBN_FP_UNIT_SIZE == 4 18 | #pragma comment(lib, "bls256.lib") 19 | #endif 20 | #endif 21 | #endif 22 | #else 23 | #define BLS_DLL_API 24 | #endif 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | typedef struct { 31 | mclBnFr v; 32 | } blsId; 33 | 34 | typedef struct { 35 | mclBnFr v; 36 | } blsSecretKey; 37 | 38 | typedef struct { 39 | mclBnG2 v; 40 | } blsPublicKey; 41 | 42 | typedef struct { 43 | mclBnG1 v; 44 | } blsSignature; 45 | 46 | /* 47 | initialize this library 48 | call this once before using the other functions 49 | @param curve [in] enum value defined in mcl/bn.h 50 | @param maxUnitSize [in] MCLBN_FP_UNIT_SIZE (fixed) 51 | return 0 if success 52 | @note blsInit() is thread safe and serialized if it is called simultaneously 53 | but don't call it while using other functions. 54 | */ 55 | BLS_DLL_API int blsInit(int curve, int maxUnitSize); 56 | 57 | // not thread safe version (old blsInit) 58 | BLS_DLL_API int blsInitNotThreadSafe(int curve, int maxUnitSize); 59 | 60 | BLS_DLL_API size_t blsGetOpUnitSize(void); 61 | // return strlen(buf) if success else 0 62 | BLS_DLL_API int blsGetCurveOrder(char *buf, size_t maxBufSize); 63 | BLS_DLL_API int blsGetFieldOrder(char *buf, size_t maxBufSize); 64 | 65 | // get a generator of G2 66 | BLS_DLL_API void blsGetGeneratorOfG2(blsPublicKey *pub); 67 | 68 | BLS_DLL_API void blsIdSetInt(blsId *id, int x); 69 | // return 0 if success 70 | BLS_DLL_API int blsIdSetDecStr(blsId *id, const char *buf, size_t bufSize); 71 | BLS_DLL_API int blsIdSetHexStr(blsId *id, const char *buf, size_t bufSize); 72 | 73 | /* 74 | return strlen(buf) if success else 0 75 | buf is '\0' terminated 76 | */ 77 | BLS_DLL_API size_t blsIdGetDecStr(char *buf, size_t maxBufSize, const blsId *id); 78 | BLS_DLL_API size_t blsIdGetHexStr(char *buf, size_t maxBufSize, const blsId *id); 79 | 80 | 81 | // return written byte size if success else 0 82 | BLS_DLL_API size_t blsIdSerialize(void *buf, size_t maxBufSize, const blsId *id); 83 | BLS_DLL_API size_t blsSecretKeySerialize(void *buf, size_t maxBufSize, const blsSecretKey *sec); 84 | BLS_DLL_API size_t blsPublicKeySerialize(void *buf, size_t maxBufSize, const blsPublicKey *pub); 85 | BLS_DLL_API size_t blsSignatureSerialize(void *buf, size_t maxBufSize, const blsSignature *sig); 86 | 87 | // return 1 if same else 0 88 | BLS_DLL_API int blsIdDeserialize(blsId *id, const void *buf, size_t bufSize); 89 | BLS_DLL_API int blsSecretKeyDeserialize(blsSecretKey *sec, const void *buf, size_t bufSize); 90 | BLS_DLL_API int blsPublicKeyDeserialize(blsPublicKey *pub, const void *buf, size_t bufSize); 91 | BLS_DLL_API int blsSignatureDeserialize(blsSignature *sig, const void *buf, size_t bufSize); 92 | 93 | // return 1 if same else 0 94 | BLS_DLL_API int blsIdIsEqual(const blsId *lhs, const blsId *rhs); 95 | BLS_DLL_API int blsSecretKeyIsEqual(const blsSecretKey *lhs, const blsSecretKey *rhs); 96 | BLS_DLL_API int blsPublicKeyIsEqual(const blsPublicKey *lhs, const blsPublicKey *rhs); 97 | BLS_DLL_API int blsSignatureIsEqual(const blsSignature *lhs, const blsSignature *rhs); 98 | 99 | // add 100 | BLS_DLL_API void blsSecretKeyAdd(blsSecretKey *sec, const blsSecretKey *rhs); 101 | BLS_DLL_API void blsPublicKeyAdd(blsPublicKey *pub, const blsPublicKey *rhs); 102 | BLS_DLL_API void blsSignatureAdd(blsSignature *sig, const blsSignature *rhs); 103 | 104 | // hash buf and set 105 | BLS_DLL_API int blsHashToSecretKey(blsSecretKey *sec, const void *buf, size_t bufSize); 106 | /* 107 | set secretKey if system has /dev/urandom or CryptGenRandom 108 | return 0 if success else -1 109 | */ 110 | BLS_DLL_API int blsSecretKeySetByCSPRNG(blsSecretKey *sec); 111 | 112 | BLS_DLL_API void blsGetPublicKey(blsPublicKey *pub, const blsSecretKey *sec); 113 | BLS_DLL_API void blsGetPop(blsSignature *sig, const blsSecretKey *sec); 114 | 115 | // return 0 if success 116 | BLS_DLL_API int blsSecretKeyShare(blsSecretKey *sec, const blsSecretKey* msk, size_t k, const blsId *id); 117 | BLS_DLL_API int blsPublicKeyShare(blsPublicKey *pub, const blsPublicKey *mpk, size_t k, const blsId *id); 118 | 119 | 120 | BLS_DLL_API int blsSecretKeyRecover(blsSecretKey *sec, const blsSecretKey *secVec, const blsId *idVec, size_t n); 121 | BLS_DLL_API int blsPublicKeyRecover(blsPublicKey *pub, const blsPublicKey *pubVec, const blsId *idVec, size_t n); 122 | BLS_DLL_API int blsSignatureRecover(blsSignature *sig, const blsSignature *sigVec, const blsId *idVec, size_t n); 123 | 124 | BLS_DLL_API void blsSign(blsSignature *sig, const blsSecretKey *sec, const void *m, size_t size); 125 | 126 | // return 1 if valid 127 | BLS_DLL_API int blsVerify(const blsSignature *sig, const blsPublicKey *pub, const void *m, size_t size); 128 | BLS_DLL_API int blsVerifyPop(const blsSignature *sig, const blsPublicKey *pub); 129 | 130 | ////////////////////////////////////////////////////////////////////////// 131 | // the following apis will be removed 132 | 133 | // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r 134 | BLS_DLL_API int blsIdSetLittleEndian(blsId *id, const void *buf, size_t bufSize); 135 | /* 136 | return written byte size if success else 0 137 | */ 138 | BLS_DLL_API size_t blsIdGetLittleEndian(void *buf, size_t maxBufSize, const blsId *id); 139 | 140 | // return 0 if success 141 | // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r 142 | BLS_DLL_API int blsSecretKeySetLittleEndian(blsSecretKey *sec, const void *buf, size_t bufSize); 143 | BLS_DLL_API int blsSecretKeySetDecStr(blsSecretKey *sec, const char *buf, size_t bufSize); 144 | BLS_DLL_API int blsSecretKeySetHexStr(blsSecretKey *sec, const char *buf, size_t bufSize); 145 | /* 146 | return written byte size if success else 0 147 | */ 148 | BLS_DLL_API size_t blsSecretKeyGetLittleEndian(void *buf, size_t maxBufSize, const blsSecretKey *sec); 149 | /* 150 | return strlen(buf) if success else 0 151 | buf is '\0' terminated 152 | */ 153 | BLS_DLL_API size_t blsSecretKeyGetDecStr(char *buf, size_t maxBufSize, const blsSecretKey *sec); 154 | BLS_DLL_API size_t blsSecretKeyGetHexStr(char *buf, size_t maxBufSize, const blsSecretKey *sec); 155 | BLS_DLL_API int blsPublicKeySetHexStr(blsPublicKey *pub, const char *buf, size_t bufSize); 156 | BLS_DLL_API size_t blsPublicKeyGetHexStr(char *buf, size_t maxBufSize, const blsPublicKey *pub); 157 | BLS_DLL_API int blsSignatureSetHexStr(blsSignature *sig, const char *buf, size_t bufSize); 158 | BLS_DLL_API size_t blsSignatureGetHexStr(char *buf, size_t maxBufSize, const blsSignature *sig); 159 | 160 | /* 161 | Diffie Hellman key exchange 162 | out = sec * pub 163 | */ 164 | BLS_DLL_API void blsDHKeyExchange(blsPublicKey *out, const blsSecretKey *sec, const blsPublicKey *pub); 165 | #ifdef __cplusplus 166 | } 167 | #endif 168 | -------------------------------------------------------------------------------- /bls/src/bls_c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../mcl/src/bn_c_impl.hpp" 9 | #define BLS_DLL_EXPORT 10 | 11 | #include 12 | /* 13 | BLS signature 14 | e : G1 x G2 -> Fp12 15 | Q in G2 ; fixed global parameter 16 | H : {str} -> G1 17 | s : secret key 18 | sQ ; public key 19 | s H(m) ; signature of m 20 | verify ; e(sQ, H(m)) = e(Q, s H(m)) 21 | */ 22 | 23 | static G2 g_Q; 24 | static std::vector g_Qcoeff; // precomputed Q 25 | static const G2& getQ() { return g_Q; } 26 | static const std::vector& getQcoeff() { return g_Qcoeff; } 27 | 28 | int blsInitNotThreadSafe(int curve, int maxUnitSize) 29 | try 30 | { 31 | if (mclBn_init(curve, maxUnitSize) != 0) return -1; 32 | BN::mapToG2(g_Q, 1); 33 | BN::precomputeG2(g_Qcoeff, getQ()); 34 | return 0; 35 | } catch (std::exception&) { 36 | return -1; 37 | } 38 | 39 | #if defined(CYBOZU_CPP_VERSION) && CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 40 | #include 41 | #define USE_STD_MUTEX 42 | #else 43 | #include 44 | #endif 45 | 46 | int blsInit(int curve, int maxUnitSize) 47 | { 48 | int ret = 0; 49 | #ifdef USE_STD_MUTEX 50 | static std::mutex m; 51 | std::lock_guard lock(m); 52 | #else 53 | static cybozu::Mutex m; 54 | cybozu::AutoLock lock(m); 55 | #endif 56 | static int g_curve = -1; 57 | if (g_curve != curve) { 58 | ret = blsInitNotThreadSafe(curve, maxUnitSize); 59 | g_curve = curve; 60 | } 61 | return ret; 62 | } 63 | 64 | static inline const mclBnG1 *cast(const G1* x) { return (const mclBnG1*)x; } 65 | static inline const mclBnG2 *cast(const G2* x) { return (const mclBnG2*)x; } 66 | 67 | /* 68 | e(P1, Q1) == e(P2, Q2) 69 | <=> finalExp(ML(P1, Q1)) == finalExp(ML(P2, Q2)) 70 | <=> finalExp(ML(P1, Q1) / ML(P2, Q2)) == 1 71 | <=> finalExp(ML(P1, Q1) * ML(-P2, Q2)) == 1 72 | Q1 is precomputed 73 | */ 74 | bool isEqualTwoPairings(const G1& P1, const Fp6* Q1coeff, const G1& P2, const G2& Q2) 75 | { 76 | std::vector Q2coeff; 77 | BN::precomputeG2(Q2coeff, Q2); 78 | Fp12 e; 79 | BN::precomputedMillerLoop2(e, P1, Q1coeff, -P2, Q2coeff.data()); 80 | BN::finalExp(e, e); 81 | return e.isOne(); 82 | } 83 | 84 | size_t checkAndCopy(char *buf, size_t maxBufSize, const std::string& s) 85 | { 86 | if (s.size() > maxBufSize + 1) { 87 | return 0; 88 | } 89 | memcpy(buf, s.c_str(), s.size()); 90 | buf[s.size()] = '\0'; 91 | return s.size(); 92 | } 93 | 94 | size_t blsGetOpUnitSize() // FpUint64Size 95 | { 96 | return Fp::getUnitSize() * sizeof(mcl::fp::Unit) / sizeof(uint64_t); 97 | } 98 | 99 | int blsGetCurveOrder(char *buf, size_t maxBufSize) 100 | try 101 | { 102 | std::string s; 103 | Fr::getModulo(s); 104 | return (int)checkAndCopy(buf, maxBufSize, s); 105 | } catch (std::exception&) { 106 | return 0; 107 | } 108 | 109 | int blsGetFieldOrder(char *buf, size_t maxBufSize) 110 | try 111 | { 112 | std::string s; 113 | Fp::getModulo(s); 114 | return (int)checkAndCopy(buf, maxBufSize, s); 115 | } catch (std::exception&) { 116 | return 0; 117 | } 118 | 119 | void blsGetGeneratorOfG2(blsPublicKey *pub) 120 | { 121 | *(G2*)pub = getQ(); 122 | } 123 | 124 | void blsGetPublicKey(blsPublicKey *pub, const blsSecretKey *sec) 125 | { 126 | mclBnG2_mul(&pub->v, cast(&getQ()), &sec->v); 127 | } 128 | void blsSign(blsSignature *sig, const blsSecretKey *sec, const void *m, size_t size) 129 | { 130 | G1 Hm; 131 | BN::hashAndMapToG1(Hm, m, size); 132 | mclBnG1_mulCT(&sig->v, cast(&Hm), &sec->v); 133 | } 134 | int blsSecretKeyShare(blsSecretKey *sec, const blsSecretKey* msk, size_t k, const blsId *id) 135 | { 136 | return mclBn_FrEvaluatePolynomial(&sec->v, &msk->v, k, &id->v); 137 | } 138 | 139 | int blsSecretKeyRecover(blsSecretKey *sec, const blsSecretKey *secVec, const blsId *idVec, size_t n) 140 | { 141 | return mclBn_FrLagrangeInterpolation(&sec->v, &idVec->v, &secVec->v, n); 142 | } 143 | 144 | void blsGetPop(blsSignature *sig, const blsSecretKey *sec) 145 | { 146 | blsPublicKey pub; 147 | blsGetPublicKey(&pub, sec); 148 | char buf[1024]; 149 | size_t n = mclBnG2_serialize(buf, sizeof(buf), &pub.v); 150 | assert(n); 151 | blsSign(sig, sec, buf, n); 152 | } 153 | int blsPublicKeyShare(blsPublicKey *pub, const blsPublicKey *mpk, size_t k, const blsId *id) 154 | { 155 | return mclBn_G2EvaluatePolynomial(&pub->v, &mpk->v, k, &id->v); 156 | } 157 | int blsPublicKeyRecover(blsPublicKey *pub, const blsPublicKey *pubVec, const blsId *idVec, size_t n) 158 | { 159 | return mclBn_G2LagrangeInterpolation(&pub->v, &idVec->v, &pubVec->v, n); 160 | } 161 | int blsSignatureRecover(blsSignature *sig, const blsSignature *sigVec, const blsId *idVec, size_t n) 162 | { 163 | return mclBn_G1LagrangeInterpolation(&sig->v, &idVec->v, &sigVec->v, n); 164 | } 165 | 166 | int blsVerify(const blsSignature *sig, const blsPublicKey *pub, const void *m, size_t size) 167 | { 168 | G1 Hm; 169 | BN::hashAndMapToG1(Hm, m, size); 170 | /* 171 | e(sHm, Q) = e(Hm, sQ) 172 | e(sig, Q) = e(Hm, pub) 173 | */ 174 | return isEqualTwoPairings(*cast(&sig->v), getQcoeff().data(), Hm, *cast(&pub->v)); 175 | } 176 | 177 | int blsVerifyPop(const blsSignature *sig, const blsPublicKey *pub) 178 | { 179 | char buf[1024]; 180 | size_t n = mclBnG2_serialize(buf, sizeof(buf), &pub->v); 181 | assert(n); 182 | return blsVerify(sig, pub, buf, n); 183 | } 184 | 185 | void blsIdSetInt(blsId *id, int x) 186 | { 187 | mclBnFr_setInt(&id->v, x); 188 | } 189 | size_t blsIdSerialize(void *buf, size_t maxBufSize, const blsId *id) 190 | { 191 | return mclBnFr_serialize(buf, maxBufSize, &id->v); 192 | } 193 | size_t blsSecretKeySerialize(void *buf, size_t maxBufSize, const blsSecretKey *sec) 194 | { 195 | return mclBnFr_serialize(buf, maxBufSize, &sec->v); 196 | } 197 | size_t blsPublicKeySerialize(void *buf, size_t maxBufSize, const blsPublicKey *pub) 198 | { 199 | return mclBnG2_serialize(buf, maxBufSize, &pub->v); 200 | } 201 | size_t blsSignatureSerialize(void *buf, size_t maxBufSize, const blsSignature *sig) 202 | { 203 | return mclBnG1_serialize(buf, maxBufSize, &sig->v); 204 | } 205 | int blsIdDeserialize(blsId *id, const void *buf, size_t bufSize) 206 | { 207 | return mclBnFr_deserialize(&id->v, buf, bufSize); 208 | } 209 | int blsSecretKeyDeserialize(blsSecretKey *sig, const void *buf, size_t bufSize) 210 | { 211 | return mclBnFr_deserialize(&sig->v, buf, bufSize); 212 | } 213 | int blsPublicKeyDeserialize(blsPublicKey *pub, const void *buf, size_t bufSize) 214 | { 215 | return mclBnG2_deserialize(&pub->v, buf, bufSize); 216 | } 217 | int blsSignatureDeserialize(blsSignature *sig, const void *buf, size_t bufSize) 218 | { 219 | return mclBnG1_deserialize(&sig->v, buf, bufSize); 220 | } 221 | int blsIdIsEqual(const blsId *lhs, const blsId *rhs) 222 | { 223 | return mclBnFr_isEqual(&lhs->v, &rhs->v); 224 | } 225 | int blsSecretKeyIsEqual(const blsSecretKey *lhs, const blsSecretKey *rhs) 226 | { 227 | return mclBnFr_isEqual(&lhs->v, &rhs->v); 228 | } 229 | int blsPublicKeyIsEqual(const blsPublicKey *lhs, const blsPublicKey *rhs) 230 | { 231 | return mclBnG2_isEqual(&lhs->v, &rhs->v); 232 | } 233 | int blsSignatureIsEqual(const blsSignature *lhs, const blsSignature *rhs) 234 | { 235 | return mclBnG1_isEqual(&lhs->v, &rhs->v); 236 | } 237 | void blsSecretKeyAdd(blsSecretKey *sec, const blsSecretKey *rhs) 238 | { 239 | mclBnFr_add(&sec->v, &sec->v, &rhs->v); 240 | } 241 | void blsSignatureAdd(blsSignature *sig, const blsSignature *rhs) 242 | { 243 | mclBnG1_add(&sig->v, &sig->v, &rhs->v); 244 | } 245 | void blsPublicKeyAdd(blsPublicKey *pub, const blsPublicKey *rhs) 246 | { 247 | mclBnG2_add(&pub->v, &pub->v, &rhs->v); 248 | } 249 | int blsIdSetLittleEndian(blsId *id, const void *buf, size_t bufSize) 250 | { 251 | return mclBnFr_setLittleEndian(&id->v, buf, bufSize); 252 | } 253 | int blsIdSetDecStr(blsId *id, const char *buf, size_t bufSize) 254 | { 255 | return mclBnFr_setStr(&id->v, buf, bufSize, 10); 256 | } 257 | int blsIdSetHexStr(blsId *id, const char *buf, size_t bufSize) 258 | { 259 | return mclBnFr_setStr(&id->v, buf, bufSize, 16); 260 | } 261 | size_t blsIdGetLittleEndian(void *buf, size_t maxBufSize, const blsId *id) 262 | { 263 | return mclBnFr_serialize(buf, maxBufSize, &id->v); 264 | } 265 | size_t blsIdGetDecStr(char *buf, size_t maxBufSize, const blsId *id) 266 | { 267 | return mclBnFr_getStr(buf, maxBufSize, &id->v, 10); 268 | } 269 | size_t blsIdGetHexStr(char *buf, size_t maxBufSize, const blsId *id) 270 | { 271 | return mclBnFr_getStr(buf, maxBufSize, &id->v, 16); 272 | } 273 | int blsSecretKeySetLittleEndian(blsSecretKey *sec, const void *buf, size_t bufSize) 274 | { 275 | return mclBnFr_setLittleEndian(&sec->v, buf, bufSize); 276 | } 277 | int blsSecretKeySetDecStr(blsSecretKey *sec, const char *buf, size_t bufSize) 278 | { 279 | return mclBnFr_setStr(&sec->v, buf, bufSize, 10); 280 | } 281 | int blsSecretKeySetHexStr(blsSecretKey *sec, const char *buf, size_t bufSize) 282 | { 283 | return mclBnFr_setStr(&sec->v, buf, bufSize, 16); 284 | } 285 | size_t blsSecretKeyGetLittleEndian(void *buf, size_t maxBufSize, const blsSecretKey *sec) 286 | { 287 | return mclBnFr_serialize(buf, maxBufSize, &sec->v); 288 | } 289 | size_t blsSecretKeyGetDecStr(char *buf, size_t maxBufSize, const blsSecretKey *sec) 290 | { 291 | return mclBnFr_getStr(buf, maxBufSize, &sec->v, 10); 292 | } 293 | size_t blsSecretKeyGetHexStr(char *buf, size_t maxBufSize, const blsSecretKey *sec) 294 | { 295 | return mclBnFr_getStr(buf, maxBufSize, &sec->v, 16); 296 | } 297 | int blsHashToSecretKey(blsSecretKey *sec, const void *buf, size_t bufSize) 298 | { 299 | return mclBnFr_setHashOf(&sec->v, buf, bufSize); 300 | } 301 | int blsSecretKeySetByCSPRNG(blsSecretKey *sec) 302 | { 303 | return mclBnFr_setByCSPRNG(&sec->v); 304 | } 305 | int blsPublicKeySetHexStr(blsPublicKey *pub, const char *buf, size_t bufSize) 306 | { 307 | return mclBnG2_setStr(&pub->v, buf, bufSize, 16); 308 | } 309 | size_t blsPublicKeyGetHexStr(char *buf, size_t maxBufSize, const blsPublicKey *pub) 310 | { 311 | return mclBnG2_getStr(buf, maxBufSize, &pub->v, 16); 312 | } 313 | int blsSignatureSetHexStr(blsSignature *sig, const char *buf, size_t bufSize) 314 | { 315 | return mclBnG1_setStr(&sig->v, buf, bufSize, 16); 316 | } 317 | size_t blsSignatureGetHexStr(char *buf, size_t maxBufSize, const blsSignature *sig) 318 | { 319 | return mclBnG1_getStr(buf, maxBufSize, &sig->v, 16); 320 | } 321 | void blsDHKeyExchange(blsPublicKey *out, const blsSecretKey *sec, const blsPublicKey *pub) 322 | { 323 | mclBnG2_mulCT(&out->v, &pub->v, &sec->v); 324 | } 325 | 326 | -------------------------------------------------------------------------------- /bn.nix: -------------------------------------------------------------------------------- 1 | { stdenv, openssl, gmpxx, llvm, ... } : 2 | stdenv.mkDerivation { 3 | name = "bn"; 4 | version="0.0.0"; 5 | src = ./.; 6 | buildInputs = [ gmpxx openssl llvm ]; 7 | installPhase = 8 | "make PREFIX=$out/ install;" + 9 | stdenv.lib.optionalString stdenv.isDarwin '' 10 | install_name_tool -change lib/libmcl.dylib $out/lib/libmcl.dylib $out/lib/libbls384.dylib 11 | install_name_tool -id $out/lib/libbls384.dylib $out/lib/libbls384.dylib 12 | install_name_tool -id $out/lib/libmcl.dylib $out/lib/libmcl.dylib 13 | ''; 14 | } 15 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/atoi.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief converter between integer and string 5 | 6 | Copyright (C) 2008 Cybozu Labs, Inc., all rights reserved. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace cybozu { 15 | 16 | namespace atoi_local { 17 | 18 | template 19 | T convertToInt(bool *b, const char *p, size_t size, const char (&max)[n], T min, T overflow1, char overflow2) 20 | { 21 | if (size > 0 && *p) { 22 | bool isMinus = false; 23 | size_t i = 0; 24 | if (*p == '-') { 25 | isMinus = true; 26 | i++; 27 | } 28 | if (i < size && p[i]) { 29 | // skip leading zero 30 | while (i < size && p[i] == '0') i++; 31 | // check minimum 32 | if (isMinus && size - i >= n - 1 && memcmp(max, &p[i], n - 1) == 0) { 33 | if (b) *b = true; 34 | return min; 35 | } 36 | T x = 0; 37 | for (;;) { 38 | unsigned char c; 39 | if (i == size || (c = static_cast(p[i])) == '\0') { 40 | if (b) *b = true; 41 | return isMinus ? -x : x; 42 | } 43 | unsigned int y = c - '0'; 44 | if (y > 9 || x > overflow1 || (x == overflow1 && c >= overflow2)) { 45 | break; 46 | } 47 | x = x * 10 + T(y); 48 | i++; 49 | } 50 | } 51 | } 52 | if (b) { 53 | *b = false; 54 | return 0; 55 | } else { 56 | throw cybozu::Exception("atoi::convertToInt") << cybozu::exception::makeString(p, size); 57 | } 58 | } 59 | 60 | template 61 | T convertToUint(bool *b, const char *p, size_t size, T overflow1, char overflow2) 62 | { 63 | if (size > 0 && *p) { 64 | size_t i = 0; 65 | // skip leading zero 66 | while (i < size && p[i] == '0') i++; 67 | T x = 0; 68 | for (;;) { 69 | unsigned char c; 70 | if (i == size || (c = static_cast(p[i])) == '\0') { 71 | if (b) *b = true; 72 | return x; 73 | } 74 | unsigned int y = c - '0'; 75 | if (y > 9 || x > overflow1 || (x == overflow1 && c >= overflow2)) { 76 | break; 77 | } 78 | x = x * 10 + T(y); 79 | i++; 80 | } 81 | } 82 | if (b) { 83 | *b = false; 84 | return 0; 85 | } else { 86 | throw cybozu::Exception("atoi::convertToUint") << cybozu::exception::makeString(p, size); 87 | } 88 | } 89 | 90 | template 91 | T convertHexToInt(bool *b, const char *p, size_t size) 92 | { 93 | if (size > 0 && *p) { 94 | size_t i = 0; 95 | T x = 0; 96 | for (;;) { 97 | unsigned int c; 98 | if (i == size || (c = static_cast(p[i])) == '\0') { 99 | if (b) *b = true; 100 | return x; 101 | } 102 | if (c - 'A' <= 'F' - 'A') { 103 | c = (c - 'A') + 10; 104 | } else if (c - 'a' <= 'f' - 'a') { 105 | c = (c - 'a') + 10; 106 | } else if (c - '0' <= '9' - '0') { 107 | c = c - '0'; 108 | } else { 109 | break; 110 | } 111 | // avoid overflow 112 | if (x > (std::numeric_limits::max)() / 16) break; 113 | x = x * 16 + T(c); 114 | i++; 115 | } 116 | } 117 | if (b) { 118 | *b = false; 119 | return 0; 120 | } else { 121 | throw cybozu::Exception("atoi::convertHexToInt") << cybozu::exception::makeString(p, size); 122 | } 123 | } 124 | 125 | } // atoi_local 126 | 127 | /** 128 | auto detect return value class 129 | @note if you set bool pointer p then throw nothing and set *p = false if bad string 130 | */ 131 | class atoi { 132 | const char *p_; 133 | size_t size_; 134 | bool *b_; 135 | void set(bool *b, const char *p, size_t size) 136 | { 137 | b_ = b; 138 | p_ = p; 139 | size_ = size; 140 | } 141 | public: 142 | atoi(const char *p, size_t size = -1) 143 | { 144 | set(0, p, size); 145 | } 146 | atoi(bool *b, const char *p, size_t size = -1) 147 | { 148 | set(b, p, size); 149 | } 150 | atoi(const std::string& str) 151 | { 152 | set(0, str.c_str(), str.size()); 153 | } 154 | atoi(bool *b, const std::string& str) 155 | { 156 | set(b, str.c_str(), str.size()); 157 | } 158 | inline operator signed char() const 159 | { 160 | return atoi_local::convertToInt(b_, p_, size_, "128", -128, 12, '8'); 161 | } 162 | inline operator unsigned char() const 163 | { 164 | return atoi_local::convertToUint(b_, p_, size_, 25, '6'); 165 | } 166 | inline operator short() const 167 | { 168 | return atoi_local::convertToInt(b_, p_, size_, "32768", -32768, 3276, '8'); 169 | } 170 | inline operator unsigned short() const 171 | { 172 | return atoi_local::convertToUint(b_, p_, size_, 6553, '6'); 173 | } 174 | inline operator int() const 175 | { 176 | return atoi_local::convertToInt(b_, p_, size_, "2147483648", INT_MIN, 214748364, '8'); 177 | } 178 | inline operator unsigned int() const 179 | { 180 | return atoi_local::convertToUint(b_, p_, size_, 429496729, '6'); 181 | } 182 | inline operator long long() const 183 | { 184 | return atoi_local::convertToInt(b_, p_, size_, "9223372036854775808", LLONG_MIN, 922337203685477580LL, '8'); 185 | } 186 | inline operator unsigned long long() const 187 | { 188 | return atoi_local::convertToUint(b_, p_, size_, 1844674407370955161ULL, '6'); 189 | } 190 | #if defined(__SIZEOF_LONG__) && (__SIZEOF_LONG__ == 8) 191 | inline operator long() const { return static_cast(static_cast(*this)); } 192 | inline operator unsigned long() const { return static_cast(static_cast(*this)); } 193 | #else 194 | inline operator long() const { return static_cast(static_cast(*this)); } 195 | inline operator unsigned long() const { return static_cast(static_cast(*this)); } 196 | #endif 197 | }; 198 | 199 | class hextoi { 200 | const char *p_; 201 | size_t size_; 202 | bool *b_; 203 | void set(bool *b, const char *p, size_t size) 204 | { 205 | b_ = b; 206 | p_ = p; 207 | size_ = size; 208 | } 209 | public: 210 | hextoi(const char *p, size_t size = -1) 211 | { 212 | set(0, p, size); 213 | } 214 | hextoi(bool *b, const char *p, size_t size = -1) 215 | { 216 | set(b, p, size); 217 | } 218 | hextoi(const std::string& str) 219 | { 220 | set(0, str.c_str(), str.size()); 221 | } 222 | hextoi(bool *b, const std::string& str) 223 | { 224 | set(b, str.c_str(), str.size()); 225 | } 226 | operator unsigned char() const { return atoi_local::convertHexToInt(b_, p_, size_); } 227 | operator unsigned short() const { return atoi_local::convertHexToInt(b_, p_, size_); } 228 | operator unsigned int() const { return atoi_local::convertHexToInt(b_, p_, size_); } 229 | operator unsigned long() const { return atoi_local::convertHexToInt(b_, p_, size_); } 230 | operator unsigned long long() const { return atoi_local::convertHexToInt(b_, p_, size_); } 231 | operator char() const { return atoi_local::convertHexToInt(b_, p_, size_); } 232 | operator signed char() const { return atoi_local::convertHexToInt(b_, p_, size_); } 233 | operator short() const { return atoi_local::convertHexToInt(b_, p_, size_); } 234 | operator int() const { return atoi_local::convertHexToInt(b_, p_, size_); } 235 | operator long() const { return atoi_local::convertHexToInt(b_, p_, size_); } 236 | operator long long() const { return atoi_local::convertHexToInt(b_, p_, size_); } 237 | }; 238 | 239 | } // cybozu 240 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/benchmark.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief measure exec time of function 5 | @author MITSUNARI Shigeo 6 | */ 7 | #if defined(_MSC_VER) && (MSC_VER <= 1500) 8 | #include 9 | #else 10 | #include 11 | #endif 12 | #include 13 | 14 | #ifdef __EMSCRIPTEN__ 15 | #define CYBOZU_BENCH_USE_GETTIMEOFDAY 16 | #endif 17 | 18 | #ifdef CYBOZU_BENCH_USE_GETTIMEOFDAY 19 | #include 20 | #elif !defined(CYBOZU_BENCH_DONT_USE_RDTSC) 21 | #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__) 22 | #define CYBOZU_BENCH_USE_RDTSC 23 | #define CYBOZU_BENCH_USE_CPU_TIMER 24 | #endif 25 | #if defined(__GNUC__) && defined(__ARM_ARCH_7A__) 26 | // #define CYBOZU_BENCH_USE_MRC 27 | // #define CYBOZU_BENCH_USE_CPU_TIMER 28 | #endif 29 | #endif 30 | 31 | 32 | #include 33 | #include 34 | #ifdef _MSC_VER 35 | #include 36 | #include 37 | #else 38 | #endif 39 | 40 | #ifndef CYBOZU_UNUSED 41 | #ifdef __GNUC__ 42 | #define CYBOZU_UNUSED __attribute__((unused)) 43 | #else 44 | #define CYBOZU_UNUSED 45 | #endif 46 | #endif 47 | 48 | namespace cybozu { 49 | 50 | class CpuClock { 51 | public: 52 | static inline uint64_t getCpuClk() 53 | { 54 | #ifdef CYBOZU_BENCH_USE_RDTSC 55 | #ifdef _MSC_VER 56 | return __rdtsc(); 57 | #else 58 | unsigned int eax, edx; 59 | __asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx)); 60 | return ((uint64_t)edx << 32) | eax; 61 | #endif 62 | #elif defined(CYBOZU_BENCH_USE_MRC) 63 | uint32_t clk; 64 | __asm__ volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(clk)); 65 | return clk; 66 | #else 67 | #ifdef _MSC_VER 68 | struct _timeb timeb; 69 | _ftime_s(&timeb); 70 | return uint64_t(timeb.time) * 1000000000 + timeb.millitm * 1000000; 71 | #elif defined(CYBOZU_BENCH_USE_GETTIMEOFDAY) 72 | struct timeval tv; 73 | int ret CYBOZU_UNUSED = gettimeofday(&tv, 0); 74 | assert(ret == 0); 75 | return uint64_t(tv.tv_sec) * 1000000000 + tv.tv_usec * 1000; 76 | #else 77 | struct timespec tp; 78 | int ret CYBOZU_UNUSED = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp); 79 | assert(ret == 0); 80 | return uint64_t(tp.tv_sec) * 1000000000 + tp.tv_nsec; 81 | #endif 82 | #endif 83 | } 84 | CpuClock() 85 | : clock_(0) 86 | , count_(0) 87 | { 88 | } 89 | void begin() 90 | { 91 | clock_ -= getCpuClk(); 92 | } 93 | void end() 94 | { 95 | clock_ += getCpuClk(); 96 | count_++; 97 | } 98 | int getCount() const { return count_; } 99 | uint64_t getClock() const { return clock_; } 100 | void clear() { count_ = 0; clock_ = 0; } 101 | void put(const char *msg = 0, int N = 1) const 102 | { 103 | double t = getClock() / double(getCount()) / N; 104 | if (msg && *msg) printf("%s ", msg); 105 | #ifdef CYBOZU_BENCH_USE_CPU_TIMER 106 | if (t > 1e6) { 107 | printf("%7.3fMclk", t * 1e-6); 108 | } else if (t > 1e3) { 109 | printf("%7.3fKclk", t * 1e-3); 110 | } else { 111 | printf("%6.2f clk", t); 112 | } 113 | #else 114 | if (t > 1e6) { 115 | printf("%7.3fmsec", t * 1e-6); 116 | } else if (t > 1e3) { 117 | printf("%7.3fusec", t * 1e-3); 118 | } else { 119 | printf("%6.2fnsec", t); 120 | } 121 | #endif 122 | if (msg && *msg) printf("\n"); 123 | } 124 | // adhoc constatns for CYBOZU_BENCH 125 | #ifdef CYBOZU_BENCH_USE_CPU_TIMER 126 | static const int loopN1 = 1000; 127 | static const int loopN2 = 100; 128 | static const uint64_t maxClk = (uint64_t)1e8; 129 | #else 130 | static const int loopN1 = 100; 131 | static const int loopN2 = 100; 132 | static const uint64_t maxClk = (uint64_t)1e8; 133 | #endif 134 | private: 135 | uint64_t clock_; 136 | int count_; 137 | }; 138 | 139 | namespace bench { 140 | 141 | static CpuClock g_clk; 142 | static int CYBOZU_UNUSED g_loopNum; 143 | 144 | } // cybozu::bench 145 | /* 146 | loop counter is automatically determined 147 | CYBOZU_BENCH(, , , , ...); 148 | if msg == "" then only set g_clk, g_loopNum 149 | */ 150 | #define CYBOZU_BENCH(msg, func, ...) \ 151 | { \ 152 | const uint64_t _cybozu_maxClk = cybozu::CpuClock::maxClk; \ 153 | cybozu::CpuClock _cybozu_clk; \ 154 | for (int _cybozu_i = 0; _cybozu_i < cybozu::CpuClock::loopN2; _cybozu_i++) { \ 155 | _cybozu_clk.begin(); \ 156 | for (int _cybozu_j = 0; _cybozu_j < cybozu::CpuClock::loopN1; _cybozu_j++) { func(__VA_ARGS__); } \ 157 | _cybozu_clk.end(); \ 158 | if (_cybozu_clk.getClock() > _cybozu_maxClk) break; \ 159 | } \ 160 | if (msg && *msg) _cybozu_clk.put(msg, cybozu::CpuClock::loopN1); \ 161 | cybozu::bench::g_clk = _cybozu_clk; cybozu::bench::g_loopNum = cybozu::CpuClock::loopN1; \ 162 | } 163 | 164 | /* 165 | double clk; 166 | CYBOZU_BENCH_T(clk, , , , ...); 167 | clk is set by CYBOZU_BENCH_T 168 | */ 169 | #define CYBOZU_BENCH_T(clk, func, ...) \ 170 | { \ 171 | const uint64_t _cybozu_maxClk = cybozu::CpuClock::maxClk; \ 172 | cybozu::CpuClock _cybozu_clk; \ 173 | for (int _cybozu_i = 0; _cybozu_i < cybozu::CpuClock::loopN2; _cybozu_i++) { \ 174 | _cybozu_clk.begin(); \ 175 | for (int _cybozu_j = 0; _cybozu_j < cybozu::CpuClock::loopN1; _cybozu_j++) { func(__VA_ARGS__); } \ 176 | _cybozu_clk.end(); \ 177 | if (_cybozu_clk.getClock() > _cybozu_maxClk) break; \ 178 | } \ 179 | clk = _cybozu_clk.getClock() / (double)_cybozu_clk.getCount() / cybozu::CpuClock::loopN1; \ 180 | } 181 | 182 | /* 183 | loop counter N is given 184 | CYBOZU_BENCH_C(, , , , , ...); 185 | if msg == "" then only set g_clk, g_loopNum 186 | */ 187 | #define CYBOZU_BENCH_C(msg, _N, func, ...) \ 188 | { \ 189 | cybozu::CpuClock _cybozu_clk; \ 190 | _cybozu_clk.begin(); \ 191 | for (int _cybozu_j = 0; _cybozu_j < _N; _cybozu_j++) { func(__VA_ARGS__); } \ 192 | _cybozu_clk.end(); \ 193 | if (msg && *msg) _cybozu_clk.put(msg, _N); \ 194 | cybozu::bench::g_clk = _cybozu_clk; cybozu::bench::g_loopNum = _N; \ 195 | } 196 | 197 | } // cybozu 198 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/bit_operation.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief bit operation 5 | */ 6 | #include 7 | #include 8 | 9 | #if (CYBOZU_HOST == CYBOZU_HOST_INTEL) 10 | #if defined(_WIN32) 11 | #include 12 | #elif defined(__linux__) || defined(__CYGWIN__) || defined(__clang__) 13 | #include 14 | #elif defined(__GNUC__) 15 | #include 16 | #endif 17 | #endif 18 | 19 | namespace cybozu { 20 | 21 | namespace bit_op_local { 22 | 23 | template 24 | struct Tag {}; 25 | 26 | // sizeof(T) < 8 27 | template<> 28 | struct Tag { 29 | template 30 | static inline int bsf(T x) 31 | { 32 | #if defined(_WIN32) 33 | unsigned long out; 34 | _BitScanForward(&out, x); 35 | #pragma warning(suppress: 6102) 36 | return out; 37 | #else 38 | return __builtin_ctz(x); 39 | #endif 40 | } 41 | template 42 | static inline int bsr(T x) 43 | { 44 | #if defined(_MSC_VER) 45 | unsigned long out; 46 | _BitScanReverse(&out, x); 47 | #pragma warning(suppress: 6102) 48 | return out; 49 | #else 50 | return __builtin_clz(x) ^ 0x1f; 51 | #endif 52 | } 53 | }; 54 | 55 | // sizeof(T) == 8 56 | template<> 57 | struct Tag { 58 | template 59 | static inline int bsf(T x) 60 | { 61 | #if defined(_MSC_VER) && defined(_WIN64) 62 | unsigned long out; 63 | _BitScanForward64(&out, x); 64 | #pragma warning(suppress: 6102) 65 | return out; 66 | #elif defined(__x86_64__) 67 | return __builtin_ctzl(x); 68 | #else 69 | const uint32_t L = uint32_t(x); 70 | if (L) return Tag::bsf(L); 71 | const uint32_t H = uint32_t(x >> 32); 72 | return Tag::bsf(H) + 32; 73 | #endif 74 | } 75 | template 76 | static inline int bsr(T x) 77 | { 78 | #if defined(_MSC_VER) && defined(_WIN64) 79 | unsigned long out; 80 | _BitScanReverse64(&out, x); 81 | #pragma warning(suppress: 6102) 82 | return out; 83 | #elif defined(__x86_64__) 84 | return __builtin_clzl(x) ^ 0x3f; 85 | #else 86 | const uint32_t H = uint32_t(x >> 32); 87 | if (H) return Tag::bsr(H) + 32; 88 | const uint32_t L = uint32_t(x); 89 | return Tag::bsr(L); 90 | #endif 91 | } 92 | }; 93 | 94 | } // bit_op_local 95 | 96 | template 97 | int bsf(T x) 98 | { 99 | return bit_op_local::Tag::bsf(x); 100 | } 101 | template 102 | int bsr(T x) 103 | { 104 | return bit_op_local::Tag::bsr(x); 105 | } 106 | 107 | template 108 | uint64_t makeBitMask64(T x) 109 | { 110 | assert(x < 64); 111 | return (uint64_t(1) << x) - 1; 112 | } 113 | 114 | template 115 | uint32_t popcnt(T x); 116 | 117 | template<> 118 | inline uint32_t popcnt(uint32_t x) 119 | { 120 | #if defined(_MSC_VER) 121 | return static_cast(_mm_popcnt_u32(x)); 122 | #else 123 | return static_cast(__builtin_popcount(x)); 124 | #endif 125 | } 126 | 127 | template<> 128 | inline uint32_t popcnt(uint64_t x) 129 | { 130 | #if defined(_WIN64) 131 | return static_cast(_mm_popcnt_u64(x)); 132 | #elif defined(__x86_64__) 133 | return static_cast(__builtin_popcountl(x)); 134 | #else 135 | return popcnt(static_cast(x)) + popcnt(static_cast(x >> 32)); 136 | #endif 137 | } 138 | 139 | } // cybozu 140 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/crypto.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief wrap openssl 5 | Copyright (C) 2012 Cybozu Labs, Inc., all rights reserved. 6 | */ 7 | 8 | #include 9 | #ifdef __APPLE__ 10 | #pragma GCC diagnostic push 11 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 12 | #endif 13 | #if 0 //#ifdef __APPLE__ 14 | #define COMMON_DIGEST_FOR_OPENSSL 15 | #include 16 | #include 17 | #define SHA1 CC_SHA1 18 | #define SHA224 CC_SHA224 19 | #define SHA256 CC_SHA256 20 | #define SHA384 CC_SHA384 21 | #define SHA512 CC_SHA512 22 | #else 23 | #include 24 | #include 25 | #include 26 | #endif 27 | #ifdef _MSC_VER 28 | #include 29 | #endif 30 | 31 | namespace cybozu { 32 | 33 | namespace crypto { 34 | 35 | class Hash { 36 | public: 37 | enum Name { 38 | N_SHA1, 39 | N_SHA224, 40 | N_SHA256, 41 | N_SHA384, 42 | N_SHA512 43 | }; 44 | private: 45 | Name name_; 46 | size_t hashSize_; 47 | union { 48 | SHA_CTX sha1; 49 | SHA256_CTX sha256; 50 | SHA512_CTX sha512; 51 | } ctx_; 52 | public: 53 | static inline size_t getSize(Name name) 54 | { 55 | switch (name) { 56 | case N_SHA1: return SHA_DIGEST_LENGTH; 57 | case N_SHA224: return SHA224_DIGEST_LENGTH; 58 | case N_SHA256: return SHA256_DIGEST_LENGTH; 59 | case N_SHA384: return SHA384_DIGEST_LENGTH; 60 | case N_SHA512: return SHA512_DIGEST_LENGTH; 61 | default: 62 | throw cybozu::Exception("crypto:Hash:getSize") << name; 63 | } 64 | } 65 | static inline const char *getName(Name name) 66 | { 67 | switch (name) { 68 | case N_SHA1: return "sha1"; 69 | case N_SHA224: return "sha224"; 70 | case N_SHA256: return "sha256"; 71 | case N_SHA384: return "sha384"; 72 | case N_SHA512: return "sha512"; 73 | default: 74 | throw cybozu::Exception("crypto:Hash:getName") << name; 75 | } 76 | } 77 | static inline Name getName(const std::string& nameStr) 78 | { 79 | static const struct { 80 | const char *nameStr; 81 | Name name; 82 | } tbl[] = { 83 | { "sha1", N_SHA1 }, 84 | { "sha224", N_SHA224 }, 85 | { "sha256", N_SHA256 }, 86 | { "sha384", N_SHA384 }, 87 | { "sha512", N_SHA512 }, 88 | }; 89 | for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { 90 | if (nameStr == tbl[i].nameStr) return tbl[i].name; 91 | } 92 | throw cybozu::Exception("crypto:Hash:getName") << nameStr; 93 | } 94 | explicit Hash(Name name = N_SHA1) 95 | : name_(name) 96 | , hashSize_(getSize(name)) 97 | { 98 | reset(); 99 | } 100 | void update(const char *buf, size_t bufSize) 101 | { 102 | switch (name_) { 103 | case N_SHA1: SHA1_Update(&ctx_.sha1, buf, bufSize); break; 104 | case N_SHA224: SHA224_Update(&ctx_.sha256, buf, bufSize); break; 105 | case N_SHA256: SHA256_Update(&ctx_.sha256, buf, bufSize); break; 106 | case N_SHA384: SHA384_Update(&ctx_.sha512, buf, bufSize); break; 107 | case N_SHA512: SHA512_Update(&ctx_.sha512, buf, bufSize); break; 108 | } 109 | } 110 | void update(const std::string& buf) 111 | { 112 | update(buf.c_str(), buf.size()); 113 | } 114 | void reset() 115 | { 116 | switch (name_) { 117 | case N_SHA1: SHA1_Init(&ctx_.sha1); break; 118 | case N_SHA224: SHA224_Init(&ctx_.sha256); break; 119 | case N_SHA256: SHA256_Init(&ctx_.sha256); break; 120 | case N_SHA384: SHA384_Init(&ctx_.sha512); break; 121 | case N_SHA512: SHA512_Init(&ctx_.sha512); break; 122 | default: 123 | throw cybozu::Exception("crypto:Hash:rset") << name_; 124 | } 125 | } 126 | /* 127 | md must have hashSize byte 128 | @note clear inner buffer after calling digest 129 | */ 130 | void digest(char *out, const char *buf, size_t bufSize) 131 | { 132 | update(buf, bufSize); 133 | unsigned char *md = reinterpret_cast(out); 134 | switch (name_) { 135 | case N_SHA1: SHA1_Final(md, &ctx_.sha1); break; 136 | case N_SHA224: SHA224_Final(md, &ctx_.sha256); break; 137 | case N_SHA256: SHA256_Final(md, &ctx_.sha256); break; 138 | case N_SHA384: SHA384_Final(md, &ctx_.sha512); break; 139 | case N_SHA512: SHA512_Final(md, &ctx_.sha512); break; 140 | default: 141 | throw cybozu::Exception("crypto:Hash:digest") << name_; 142 | } 143 | reset(); 144 | } 145 | std::string digest(const char *buf, size_t bufSize) 146 | { 147 | std::string ret; 148 | ret.resize(hashSize_); 149 | digest(&ret[0], buf, bufSize); 150 | return ret; 151 | } 152 | std::string digest(const std::string& buf = "") 153 | { 154 | return digest(buf.c_str(), buf.size()); 155 | } 156 | static inline std::string digest(Name name, const char *buf, size_t bufSize) 157 | { 158 | unsigned char md[128]; 159 | const unsigned char *src = cybozu::cast(buf); 160 | switch (name) { 161 | case N_SHA1: SHA1(src, bufSize, md); break; 162 | case N_SHA224: SHA224(src, bufSize, md); break; 163 | case N_SHA256: SHA256(src, bufSize, md); break; 164 | case N_SHA384: SHA384(src, bufSize, md); break; 165 | case N_SHA512: SHA512(src, bufSize, md); break; 166 | default: 167 | throw cybozu::Exception("crypt:Hash:digest") << name; 168 | } 169 | return std::string(cybozu::cast(md), getSize(name)); 170 | } 171 | static inline std::string digest(Name name, const std::string& buf) 172 | { 173 | return digest(name, buf.c_str(), buf.size()); 174 | } 175 | }; 176 | 177 | class Hmac { 178 | const EVP_MD *evp_; 179 | public: 180 | explicit Hmac(Hash::Name name = Hash::N_SHA1) 181 | { 182 | switch (name) { 183 | case Hash::N_SHA1: evp_ = EVP_sha1(); break; 184 | case Hash::N_SHA224: evp_ = EVP_sha224(); break; 185 | case Hash::N_SHA256: evp_ = EVP_sha256(); break; 186 | case Hash::N_SHA384: evp_ = EVP_sha384(); break; 187 | case Hash::N_SHA512: evp_ = EVP_sha512(); break; 188 | default: 189 | throw cybozu::Exception("crypto:Hmac:") << name; 190 | } 191 | } 192 | std::string eval(const std::string& key, const std::string& data) 193 | { 194 | std::string out(EVP_MD_size(evp_) + 1, 0); 195 | unsigned int outLen = 0; 196 | if (HMAC(evp_, key.c_str(), static_cast(key.size()), 197 | cybozu::cast(data.c_str()), data.size(), cybozu::cast(&out[0]), &outLen)) { 198 | out.resize(outLen); 199 | return out; 200 | } 201 | throw cybozu::Exception("crypto::Hamc::eval"); 202 | } 203 | }; 204 | 205 | class Cipher { 206 | const EVP_CIPHER *cipher_; 207 | EVP_CIPHER_CTX *ctx_; 208 | public: 209 | enum Name { 210 | N_AES128_CBC, 211 | N_AES192_CBC, 212 | N_AES256_CBC, 213 | N_AES128_ECB, // be carefull to use 214 | N_AES192_ECB, // be carefull to use 215 | N_AES256_ECB, // be carefull to use 216 | }; 217 | static inline size_t getSize(Name name) 218 | { 219 | switch (name) { 220 | case N_AES128_CBC: return 128; 221 | case N_AES192_CBC: return 192; 222 | case N_AES256_CBC: return 256; 223 | case N_AES128_ECB: return 128; 224 | case N_AES192_ECB: return 192; 225 | case N_AES256_ECB: return 256; 226 | default: 227 | throw cybozu::Exception("crypto:Cipher:getSize") << name; 228 | } 229 | } 230 | enum Mode { 231 | Decoding, 232 | Encoding 233 | }; 234 | explicit Cipher(Name name = N_AES128_CBC) 235 | : cipher_(0) 236 | , ctx_(0) 237 | { 238 | ctx_ = EVP_CIPHER_CTX_new(); 239 | if (ctx_ == 0) throw cybozu::Exception("crypto:Cipher:EVP_CIPHER_CTX_new"); 240 | switch (name) { 241 | case N_AES128_CBC: cipher_ = EVP_aes_128_cbc(); break; 242 | case N_AES192_CBC: cipher_ = EVP_aes_192_cbc(); break; 243 | case N_AES256_CBC: cipher_ = EVP_aes_256_cbc(); break; 244 | case N_AES128_ECB: cipher_ = EVP_aes_128_ecb(); break; 245 | case N_AES192_ECB: cipher_ = EVP_aes_192_ecb(); break; 246 | case N_AES256_ECB: cipher_ = EVP_aes_256_ecb(); break; 247 | default: 248 | throw cybozu::Exception("crypto:Cipher:Cipher:name") << (int)name; 249 | } 250 | } 251 | ~Cipher() 252 | { 253 | if (ctx_) EVP_CIPHER_CTX_free(ctx_); 254 | } 255 | /* 256 | @note don't use padding = true 257 | */ 258 | void setup(Mode mode, const std::string& key, const std::string& iv, bool padding = false) 259 | { 260 | const int keyLen = static_cast(key.size()); 261 | const int expectedKeyLen = EVP_CIPHER_key_length(cipher_); 262 | if (keyLen != expectedKeyLen) { 263 | throw cybozu::Exception("crypto:Cipher:setup:keyLen") << keyLen << expectedKeyLen; 264 | } 265 | 266 | int ret = EVP_CipherInit_ex(ctx_, cipher_, NULL, cybozu::cast(key.c_str()), cybozu::cast(iv.c_str()), mode == Encoding ? 1 : 0); 267 | if (ret != 1) { 268 | throw cybozu::Exception("crypto:Cipher:setup:EVP_CipherInit_ex") << ret; 269 | } 270 | ret = EVP_CIPHER_CTX_set_padding(ctx_, padding ? 1 : 0); 271 | if (ret != 1) { 272 | throw cybozu::Exception("crypto:Cipher:setup:EVP_CIPHER_CTX_set_padding") << ret; 273 | } 274 | /* 275 | const int ivLen = static_cast(iv.size()); 276 | const int expectedIvLen = EVP_CIPHER_CTX_iv_length(&ctx_); 277 | if (ivLen != expectedIvLen) { 278 | throw cybozu::Exception("crypto:Cipher:setup:ivLen") << ivLen << expectedIvLen; 279 | } 280 | */ 281 | } 282 | /* 283 | the size of outBuf must be larger than inBufSize + blockSize 284 | @retval positive or 0 : writeSize(+blockSize) 285 | @retval -1 : error 286 | */ 287 | int update(char *outBuf, const char *inBuf, int inBufSize) 288 | { 289 | int outLen = 0; 290 | int ret = EVP_CipherUpdate(ctx_, cybozu::cast(outBuf), &outLen, cybozu::cast(inBuf), inBufSize); 291 | if (ret != 1) return -1; 292 | return outLen; 293 | } 294 | /* 295 | return -1 if padding 296 | @note don't use 297 | */ 298 | int finalize(char *outBuf) 299 | { 300 | int outLen = 0; 301 | int ret = EVP_CipherFinal_ex(ctx_, cybozu::cast(outBuf), &outLen); 302 | if (ret != 1) return -1; 303 | return outLen; 304 | } 305 | }; 306 | 307 | } } // cybozu::crypto 308 | 309 | #ifdef __APPLE__ 310 | #pragma GCC diagnostic pop 311 | #endif 312 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/endian.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | @file 5 | @brief deal with big and little endian 6 | 7 | Copyright (C) 2008 Cybozu Labs, Inc., all rights reserved. 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace cybozu { 15 | 16 | #ifdef _MSC_VER 17 | inline uint16_t byteSwap(uint16_t x) { return _byteswap_ushort(x); } 18 | inline uint32_t byteSwap(uint32_t x) { return _byteswap_ulong(x); } 19 | inline uint64_t byteSwap(uint64_t x) { return _byteswap_uint64(x); } 20 | #else 21 | #if (((__GNUC__) << 16) + (__GNUC_MINOR__)) >= ((4 << 16) + 8) 22 | inline uint16_t byteSwap(uint16_t x) { return __builtin_bswap16(x); } 23 | #else 24 | inline uint16_t byteSwap(uint16_t x) { return (x >> 8) | (x << 8); } 25 | #endif 26 | inline uint32_t byteSwap(uint32_t x) { return __builtin_bswap32(x); } 27 | inline uint64_t byteSwap(uint64_t x) { return __builtin_bswap64(x); } 28 | #endif 29 | 30 | /** 31 | get 16bit integer as little endian 32 | @param src [in] pointer 33 | */ 34 | inline uint16_t Get16bitAsLE(const void *src) 35 | { 36 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 37 | uint16_t x; 38 | memcpy(&x, src, sizeof(x)); 39 | return x; 40 | #else 41 | const uint8_t *p = static_cast(src); 42 | return p[0] | (p[1] << 8); 43 | #endif 44 | } 45 | 46 | /** 47 | get 32bit integer as little endian 48 | @param src [in] pointer 49 | */ 50 | inline uint32_t Get32bitAsLE(const void *src) 51 | { 52 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 53 | uint32_t x; 54 | memcpy(&x, src, sizeof(x)); 55 | return x; 56 | #else 57 | const uint8_t *p = static_cast(src); 58 | return Get16bitAsLE(p) | (static_cast(Get16bitAsLE(p + 2)) << 16); 59 | #endif 60 | } 61 | 62 | /** 63 | get 64bit integer as little endian 64 | @param src [in] pointer 65 | */ 66 | inline uint64_t Get64bitAsLE(const void *src) 67 | { 68 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 69 | uint64_t x; 70 | memcpy(&x, src, sizeof(x)); 71 | return x; 72 | #else 73 | const uint8_t *p = static_cast(src); 74 | return Get32bitAsLE(p) | (static_cast(Get32bitAsLE(p + 4)) << 32); 75 | #endif 76 | } 77 | 78 | /** 79 | get 16bit integer as bit endian 80 | @param src [in] pointer 81 | */ 82 | inline uint16_t Get16bitAsBE(const void *src) 83 | { 84 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 85 | uint16_t x; 86 | memcpy(&x, src, sizeof(x)); 87 | return byteSwap(x); 88 | #else 89 | const uint8_t *p = static_cast(src); 90 | return p[1] | (p[0] << 8); 91 | #endif 92 | } 93 | 94 | /** 95 | get 32bit integer as bit endian 96 | @param src [in] pointer 97 | */ 98 | inline uint32_t Get32bitAsBE(const void *src) 99 | { 100 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 101 | uint32_t x; 102 | memcpy(&x, src, sizeof(x)); 103 | return byteSwap(x); 104 | #else 105 | const uint8_t *p = static_cast(src); 106 | return Get16bitAsBE(p + 2) | (static_cast(Get16bitAsBE(p)) << 16); 107 | #endif 108 | } 109 | 110 | /** 111 | get 64bit integer as big endian 112 | @param src [in] pointer 113 | */ 114 | inline uint64_t Get64bitAsBE(const void *src) 115 | { 116 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 117 | uint64_t x; 118 | memcpy(&x, src, sizeof(x)); 119 | return byteSwap(x); 120 | #else 121 | const uint8_t *p = static_cast(src); 122 | return Get32bitAsBE(p + 4) | (static_cast(Get32bitAsBE(p)) << 32); 123 | #endif 124 | } 125 | 126 | /** 127 | set 16bit integer as little endian 128 | @param src [out] pointer 129 | @param x [in] integer 130 | */ 131 | inline void Set16bitAsLE(void *src, uint16_t x) 132 | { 133 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 134 | memcpy(src, &x, sizeof(x)); 135 | #else 136 | uint8_t *p = static_cast(src); 137 | p[0] = static_cast(x); 138 | p[1] = static_cast(x >> 8); 139 | #endif 140 | } 141 | /** 142 | set 32bit integer as little endian 143 | @param src [out] pointer 144 | @param x [in] integer 145 | */ 146 | inline void Set32bitAsLE(void *src, uint32_t x) 147 | { 148 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 149 | memcpy(src, &x, sizeof(x)); 150 | #else 151 | uint8_t *p = static_cast(src); 152 | p[0] = static_cast(x); 153 | p[1] = static_cast(x >> 8); 154 | p[2] = static_cast(x >> 16); 155 | p[3] = static_cast(x >> 24); 156 | #endif 157 | } 158 | /** 159 | set 64bit integer as little endian 160 | @param src [out] pointer 161 | @param x [in] integer 162 | */ 163 | inline void Set64bitAsLE(void *src, uint64_t x) 164 | { 165 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 166 | memcpy(src, &x, sizeof(x)); 167 | #else 168 | uint8_t *p = static_cast(src); 169 | Set32bitAsLE(p, static_cast(x)); 170 | Set32bitAsLE(p + 4, static_cast(x >> 32)); 171 | #endif 172 | } 173 | /** 174 | set 16bit integer as big endian 175 | @param src [out] pointer 176 | @param x [in] integer 177 | */ 178 | inline void Set16bitAsBE(void *src, uint16_t x) 179 | { 180 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 181 | x = byteSwap(x); 182 | memcpy(src, &x, sizeof(x)); 183 | #else 184 | uint8_t *p = static_cast(src); 185 | p[0] = static_cast(x >> 8); 186 | p[1] = static_cast(x); 187 | #endif 188 | } 189 | /** 190 | set 32bit integer as big endian 191 | @param src [out] pointer 192 | @param x [in] integer 193 | */ 194 | inline void Set32bitAsBE(void *src, uint32_t x) 195 | { 196 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 197 | x = byteSwap(x); 198 | memcpy(src, &x, sizeof(x)); 199 | #else 200 | uint8_t *p = static_cast(src); 201 | p[0] = static_cast(x >> 24); 202 | p[1] = static_cast(x >> 16); 203 | p[2] = static_cast(x >> 8); 204 | p[3] = static_cast(x); 205 | #endif 206 | } 207 | /** 208 | set 64bit integer as big endian 209 | @param src [out] pointer 210 | @param x [in] integer 211 | */ 212 | inline void Set64bitAsBE(void *src, uint64_t x) 213 | { 214 | #if CYBOZU_ENDIAN == CYBOZU_ENDIAN_LITTLE 215 | x = byteSwap(x); 216 | memcpy(src, &x, sizeof(x)); 217 | #else 218 | uint8_t *p = static_cast(src); 219 | Set32bitAsBE(p, static_cast(x >> 32)); 220 | Set32bitAsBE(p + 4, static_cast(x)); 221 | #endif 222 | } 223 | 224 | } // cybozu 225 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/exception.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief definition of abstruct exception class 5 | Copyright (C) 2008 Cybozu Labs, Inc., all rights reserved. 6 | */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #ifdef _WIN32 13 | #include 14 | #include 15 | #else 16 | #include // for strerror_r 17 | #endif 18 | #include 19 | #ifdef CYBOZU_EXCEPTION_WITH_STACKTRACE 20 | #include 21 | #endif 22 | 23 | namespace cybozu { 24 | 25 | const bool DontThrow = true; 26 | 27 | namespace exception { 28 | 29 | /* get max 16 characters to avoid buffer overrun */ 30 | inline std::string makeString(const char *str, size_t size) 31 | { 32 | return std::string(str, std::min(size, 16)); 33 | } 34 | 35 | #ifdef _WIN32 36 | inline std::string wstr2str(const std::wstring& wstr) 37 | { 38 | std::string str; 39 | for (size_t i = 0; i < wstr.size(); i++) { 40 | uint16_t c = wstr[i]; 41 | if (c < 0x80) { 42 | str += char(c); 43 | } else { 44 | char buf[16]; 45 | CYBOZU_SNPRINTF(buf, sizeof(buf), "\\u%04x", c); 46 | str += buf; 47 | } 48 | } 49 | return str; 50 | } 51 | #endif 52 | 53 | } // cybozu::exception 54 | 55 | /** 56 | convert errno to string 57 | @param err [in] errno 58 | @note for both windows and linux 59 | */ 60 | inline std::string ConvertErrorNoToString(int err) 61 | { 62 | char errBuf[256]; 63 | std::string ret; 64 | #ifdef _WIN32 65 | if (strerror_s(errBuf, sizeof(errBuf), err) == 0) { 66 | ret = errBuf; 67 | } else { 68 | ret = "err"; 69 | } 70 | #elif defined(_GNU_SOURCE) 71 | ret = ::strerror_r(err, errBuf, sizeof(errBuf)); 72 | #else 73 | if (strerror_r(err, errBuf, sizeof(errBuf)) == 0) { 74 | ret = errBuf; 75 | } else { 76 | ret = "err"; 77 | } 78 | #endif 79 | char buf2[64]; 80 | CYBOZU_SNPRINTF(buf2, sizeof(buf2), "(%d)", err); 81 | ret += buf2; 82 | return ret; 83 | } 84 | 85 | class Exception : public std::exception { 86 | mutable std::string str_; 87 | #ifdef CYBOZU_EXCEPTION_WITH_STACKTRACE 88 | mutable std::string stackTrace_; 89 | #endif 90 | public: 91 | explicit Exception(const std::string& name = "", bool enableStackTrace = true) 92 | : str_(name) 93 | { 94 | #ifdef CYBOZU_EXCEPTION_WITH_STACKTRACE 95 | if (enableStackTrace) stackTrace_ = cybozu::StackTrace().toString(); 96 | #else 97 | cybozu::disable_warning_unused_variable(enableStackTrace); 98 | #endif 99 | } 100 | ~Exception() throw() {} 101 | const char *what() const throw() { return toString().c_str(); } 102 | const std::string& toString() const throw() 103 | { 104 | #ifdef CYBOZU_EXCEPTION_WITH_STACKTRACE 105 | try { 106 | if (!stackTrace_.empty()) { 107 | #ifdef CYBOZU_STACKTRACE_ONELINE 108 | str_ += "\n<<>> "; 109 | str_ += stackTrace_; 110 | #else 111 | str_ += "\n<< 139 | Exception& operator<<(const T& x) 140 | { 141 | std::ostringstream os; 142 | os << x; 143 | return operator<<(os.str()); 144 | } 145 | }; 146 | 147 | class ErrorNo { 148 | public: 149 | #ifdef _WIN32 150 | typedef unsigned int NativeErrorNo; 151 | #else 152 | typedef int NativeErrorNo; 153 | #endif 154 | explicit ErrorNo(NativeErrorNo err) 155 | : err_(err) 156 | { 157 | } 158 | ErrorNo() 159 | : err_(getLatestNativeErrorNo()) 160 | { 161 | } 162 | NativeErrorNo getLatestNativeErrorNo() const 163 | { 164 | #ifdef _WIN32 165 | return ::GetLastError(); 166 | #else 167 | return errno; 168 | #endif 169 | } 170 | /** 171 | convert NativeErrNo to string(maybe UTF8) 172 | @param err [in] errno 173 | @note Linux : same as ConvertErrorNoToString 174 | Windows : for Win32 API(use en-us) 175 | */ 176 | std::string toString() const 177 | { 178 | #ifdef _WIN32 179 | const int msgSize = 256; 180 | wchar_t msg[msgSize]; 181 | int size = FormatMessageW( 182 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 183 | 0, 184 | err_, 185 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 186 | msg, 187 | msgSize, 188 | NULL 189 | ); 190 | if (size <= 0) return ""; 191 | // remove last "\r\n" 192 | if (size > 2 && msg[size - 2] == '\r') { 193 | msg[size - 2] = 0; 194 | size -= 2; 195 | } 196 | std::string ret; 197 | ret.resize(size); 198 | // assume ascii only 199 | for (int i = 0; i < size; i++) { 200 | ret[i] = (char)msg[i]; 201 | } 202 | char buf2[64]; 203 | CYBOZU_SNPRINTF(buf2, sizeof(buf2), "(%u)", err_); 204 | ret += buf2; 205 | return ret; 206 | #else 207 | return ConvertErrorNoToString(err_); 208 | #endif 209 | } 210 | private: 211 | NativeErrorNo err_; 212 | }; 213 | 214 | inline std::ostream& operator<<(std::ostream& os, const cybozu::ErrorNo& self) 215 | { 216 | return os << self.toString(); 217 | } 218 | 219 | } // cybozu 220 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/hash.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace cybozu { 5 | 6 | template 7 | uint32_t hash32(Iter begin, Iter end, uint32_t v = 0) 8 | { 9 | if (v == 0) v = 2166136261U; 10 | while (begin != end) { 11 | v ^= *begin++; 12 | v *= 16777619; 13 | } 14 | return v; 15 | } 16 | template 17 | uint64_t hash64(Iter begin, Iter end, uint64_t v = 0) 18 | { 19 | if (v == 0) v = 14695981039346656037ULL; 20 | while (begin != end) { 21 | v ^= *begin++; 22 | v *= 1099511628211ULL; 23 | } 24 | v ^= v >> 32; 25 | return v; 26 | } 27 | template 28 | uint32_t hash32(const T *x, size_t n, uint32_t v = 0) 29 | { 30 | return hash32(x, x + n, v); 31 | } 32 | template 33 | uint64_t hash64(const T *x, size_t n, uint64_t v = 0) 34 | { 35 | return hash64(x, x + n, v); 36 | } 37 | 38 | } // cybozu 39 | 40 | namespace boost { 41 | 42 | template 43 | struct hash; 44 | 45 | } // boost 46 | 47 | namespace std { CYBOZU_NAMESPACE_TR1_BEGIN 48 | 49 | #ifdef _MSC_VER 50 | #pragma warning(push) 51 | #pragma warning(disable : 4099) // missmatch class and struct 52 | #endif 53 | #ifndef __APPLE__ 54 | template 55 | struct hash; 56 | #endif 57 | #ifdef _MSC_VER 58 | #pragma warning(pop) 59 | #endif 60 | 61 | CYBOZU_NAMESPACE_TR1_END } // std 62 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/inttype.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief int type definition and macros 5 | Copyright (C) 2008 Cybozu Labs, Inc., all rights reserved. 6 | */ 7 | 8 | #if defined(_MSC_VER) && (MSC_VER <= 1500) && !defined(CYBOZU_DEFINED_INTXX) 9 | #define CYBOZU_DEFINED_INTXX 10 | typedef __int64 int64_t; 11 | typedef unsigned __int64 uint64_t; 12 | typedef unsigned int uint32_t; 13 | typedef int int32_t; 14 | typedef unsigned short uint16_t; 15 | typedef short int16_t; 16 | typedef unsigned char uint8_t; 17 | typedef signed char int8_t; 18 | #else 19 | #include 20 | #endif 21 | 22 | #ifdef _MSC_VER 23 | #ifndef CYBOZU_DEFINED_SSIZE_T 24 | #define CYBOZU_DEFINED_SSIZE_T 25 | #ifdef _WIN64 26 | typedef int64_t ssize_t; 27 | #else 28 | typedef int32_t ssize_t; 29 | #endif 30 | #endif 31 | #else 32 | #include // for ssize_t 33 | #endif 34 | 35 | #ifndef CYBOZU_ALIGN 36 | #ifdef _MSC_VER 37 | #define CYBOZU_ALIGN(x) __declspec(align(x)) 38 | #else 39 | #define CYBOZU_ALIGN(x) __attribute__((aligned(x))) 40 | #endif 41 | #endif 42 | #ifndef CYBOZU_FORCE_INLINE 43 | #ifdef _MSC_VER 44 | #define CYBOZU_FORCE_INLINE __forceinline 45 | #else 46 | #define CYBOZU_FORCE_INLINE __attribute__((always_inline)) 47 | #endif 48 | #endif 49 | #ifndef CYBOZU_UNUSED 50 | #ifdef __GNUC__ 51 | #define CYBOZU_UNUSED __attribute__((unused)) 52 | #else 53 | #define CYBOZU_UNUSED 54 | #endif 55 | #endif 56 | #ifndef CYBOZU_ALLOCA 57 | #ifdef _MSC_VER 58 | #include 59 | #define CYBOZU_ALLOCA(x) _malloca(x) 60 | #else 61 | #define CYBOZU_ALLOCA(x) __builtin_alloca(x) 62 | #endif 63 | #endif 64 | #ifndef CYBOZU_NUM_OF_ARRAY 65 | #define CYBOZU_NUM_OF_ARRAY(x) (sizeof(x) / sizeof(*x)) 66 | #endif 67 | #ifndef CYBOZU_SNPRINTF 68 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 69 | #define CYBOZU_SNPRINTF(x, len, ...) (void)_snprintf_s(x, len, len - 1, __VA_ARGS__) 70 | #else 71 | #define CYBOZU_SNPRINTF(x, len, ...) (void)snprintf(x, len, __VA_ARGS__) 72 | #endif 73 | #endif 74 | 75 | #define CYBOZU_CPP_VERSION_CPP03 0 76 | #define CYBOZU_CPP_VERSION_TR1 1 77 | #define CYBOZU_CPP_VERSION_CPP11 2 78 | 79 | #ifdef __GNUC__ 80 | #define CYBOZU_GNUC_PREREQ(major, minor) ((__GNUC__) * 100 + (__GNUC_MINOR__) >= (major) * 100 + (minor)) 81 | #else 82 | #define CYBOZU_GNUC_PREREQ(major, minor) 0 83 | #endif 84 | 85 | #if (__cplusplus >= 201103) || (_MSC_VER >= 1500) || defined(__GXX_EXPERIMENTAL_CXX0X__) 86 | #if defined(_MSC_VER) && (_MSC_VER <= 1600) 87 | #define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1 88 | #else 89 | #define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP11 90 | #endif 91 | #elif CYBOZU_GNUC_PREREQ(4, 5) || (CYBOZU_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || (__clang_major__ >= 3) 92 | #define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_TR1 93 | #else 94 | #define CYBOZU_CPP_VERSION CYBOZU_CPP_VERSION_CPP03 95 | #endif 96 | 97 | #ifdef CYBOZU_USE_BOOST 98 | #define CYBOZU_NAMESPACE_STD boost 99 | #define CYBOZU_NAMESPACE_TR1_BEGIN 100 | #define CYBOZU_NAMESPACE_TR1_END 101 | #elif (CYBOZU_CPP_VERSION == CYBOZU_CPP_VERSION_TR1) && !defined(__APPLE__) 102 | #define CYBOZU_NAMESPACE_STD std::tr1 103 | #define CYBOZU_NAMESPACE_TR1_BEGIN namespace tr1 { 104 | #define CYBOZU_NAMESPACE_TR1_END } 105 | #else 106 | #define CYBOZU_NAMESPACE_STD std 107 | #define CYBOZU_NAMESPACE_TR1_BEGIN 108 | #define CYBOZU_NAMESPACE_TR1_END 109 | #endif 110 | 111 | #ifndef CYBOZU_OS_BIT 112 | #if defined(_WIN64) || defined(__x86_64__) || defined(__AARCH64EL__) || defined(__EMSCRIPTEN__) 113 | #define CYBOZU_OS_BIT 64 114 | #else 115 | #define CYBOZU_OS_BIT 32 116 | #endif 117 | #endif 118 | 119 | #ifndef CYBOZU_HOST 120 | #define CYBOZU_HOST_UNKNOWN 0 121 | #define CYBOZU_HOST_INTEL 1 122 | #define CYBOZU_HOST_ARM 2 123 | #if defined(_M_IX86) || defined(_M_AMD64) || defined(__x86_64__) || defined(__i386__) 124 | #define CYBOZU_HOST CYBOZU_HOST_INTEL 125 | #elif defined(__arm__) || defined(__AARCH64EL__) 126 | #define CYBOZU_HOST CYBOZU_HOST_ARM 127 | #else 128 | #define CYBOZU_HOST CYBOZU_HOST_UNKNOWN 129 | #endif 130 | #endif 131 | 132 | #ifndef CYBOZU_ENDIAN 133 | #define CYBOZU_ENDIAN_UNKNOWN 0 134 | #define CYBOZU_ENDIAN_LITTLE 1 135 | #define CYBOZU_ENDIAN_BIG 2 136 | #if (CYBOZU_HOST == CYBOZU_HOST_INTEL) 137 | #define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE 138 | #elif (CYBOZU_HOST == CYBOZU_HOST_ARM) && (defined(__ARM_EABI__) || defined(__AARCH64EL__)) 139 | #define CYBOZU_ENDIAN CYBOZU_ENDIAN_LITTLE 140 | #else 141 | #define CYBOZU_ENDIAN CYBOZU_ENDIAN_UNKNOWN 142 | #endif 143 | #endif 144 | 145 | namespace cybozu { 146 | template 147 | void disable_warning_unused_variable(const T&) { } 148 | template 149 | T cast(const S* ptr) { return static_cast(static_cast(ptr)); } 150 | template 151 | T cast(S* ptr) { return static_cast(static_cast(ptr)); } 152 | } // cybozu 153 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/itoa.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief convert integer to string(ascii) 5 | 6 | Copyright (C) 2008 Cybozu Labs, Inc., all rights reserved. 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace cybozu { 14 | 15 | template 16 | size_t getHexLength(T x) 17 | { 18 | return x == 0 ? 1 : cybozu::bsr(x) / 4 + 1; 19 | } 20 | /* 21 | convert x to hex string with len 22 | @note out should have getHexLength(x) size 23 | out is not NUL terminated 24 | */ 25 | template 26 | void itohex(char *out, size_t len, T x, bool upCase = true) 27 | { 28 | static const char *hexTbl[] = { 29 | "0123456789abcdef", 30 | "0123456789ABCDEF" 31 | }; 32 | const char *tbl = hexTbl[upCase]; 33 | for (size_t i = 0; i < len; i++) { 34 | out[len - i - 1] = tbl[x % 16]; 35 | x /= 16; 36 | } 37 | } 38 | 39 | template 40 | size_t getBinLength(T x) 41 | { 42 | return x == 0 ? 1 : cybozu::bsr(x) + 1; 43 | } 44 | /* 45 | convert x to bin string with len 46 | @note out should have getBinLength(x) size 47 | out is not NUL terminated 48 | */ 49 | template 50 | void itobin(char *out, size_t len, T x) 51 | { 52 | for (size_t i = 0; i < len; i++) { 53 | out[len - i - 1] = '0' + (x & 1); 54 | x >>= 1; 55 | } 56 | } 57 | 58 | namespace itoa_local { 59 | 60 | template 61 | void convertFromInt(std::string& out, T x, T minusMax, const char (&minusMaxStr)[n]) 62 | { 63 | if (x == minusMax) { 64 | out.assign(minusMaxStr, minusMaxStr + n - 1); 65 | return; 66 | } 67 | if (x == 0) { 68 | out.assign(1, '0'); 69 | return; 70 | } 71 | UT absX = x < 0 ? -x : x; 72 | char buf[40]; 73 | int p = 0; 74 | while (absX > 0) { 75 | buf[p++] = '0' + static_cast(absX % 10); 76 | absX /= 10; 77 | } 78 | if (x < 0) { 79 | buf[p++] = '-'; 80 | } 81 | out.resize(p); 82 | for (int i = 0; i < p; i++) { 83 | out[i] = buf[p - 1 - i]; 84 | } 85 | } 86 | 87 | template 88 | void convertFromUint(std::string& out, T x) 89 | { 90 | if (x == 0) { 91 | out.assign(1, '0'); 92 | return; 93 | } 94 | char buf[40]; 95 | int p = 0; 96 | while (x > 0) { 97 | buf[p++] = '0' + static_cast(x % 10); 98 | x /= 10; 99 | } 100 | out.resize(p); 101 | for (int i = 0; i < p; i++) { 102 | out[i] = buf[p - 1 - i]; 103 | } 104 | } 105 | 106 | template 107 | void itohexLocal(std::string& out, T x, bool upCase, bool withZero) 108 | { 109 | const size_t size = withZero ? sizeof(T) * 2 : getHexLength(x); 110 | out.resize(size); 111 | itohex(&out[0], size, x, upCase); 112 | } 113 | 114 | template 115 | void itobinLocal(std::string& out, T x, bool withZero) 116 | { 117 | const size_t size = withZero ? sizeof(T) * 8 : getBinLength(x); 118 | out.resize(size); 119 | itobin(&out[0], size, x); 120 | } 121 | 122 | } // itoa_local 123 | 124 | /** 125 | convert int to string 126 | @param out [out] string 127 | @param x [in] int 128 | */ 129 | inline void itoa(std::string& out, int x) 130 | { 131 | itoa_local::convertFromInt(out, x, INT_MIN, "-2147483648"); 132 | } 133 | 134 | /** 135 | convert long long to string 136 | @param out [out] string 137 | @param x [in] long long 138 | */ 139 | inline void itoa(std::string& out, long long x) 140 | { 141 | itoa_local::convertFromInt(out, x, LLONG_MIN, "-9223372036854775808"); 142 | } 143 | 144 | /** 145 | convert unsigned int to string 146 | @param out [out] string 147 | @param x [in] unsigned int 148 | */ 149 | inline void itoa(std::string& out, unsigned int x) 150 | { 151 | itoa_local::convertFromUint(out, x); 152 | } 153 | 154 | /** 155 | convert unsigned long long to string 156 | @param out [out] string 157 | @param x [in] unsigned long long 158 | */ 159 | inline void itoa(std::string& out, unsigned long long x) 160 | { 161 | itoa_local::convertFromUint(out, x); 162 | } 163 | 164 | #if defined(__SIZEOF_LONG__) && (__SIZEOF_LONG__ == 8) 165 | inline void itoa(std::string& out, long x) { itoa(out, static_cast(x)); } 166 | inline void itoa(std::string& out, unsigned long x) { itoa(out, static_cast(x)); } 167 | #else 168 | inline void itoa(std::string& out, long x) { itoa(out, static_cast(x)); } 169 | inline void itoa(std::string& out, unsigned long x) { itoa(out, static_cast(x)); } 170 | #endif 171 | /** 172 | convert integer to string 173 | @param x [in] int 174 | */ 175 | template 176 | inline std::string itoa(T x) 177 | { 178 | std::string ret; 179 | itoa(ret, x); 180 | return ret; 181 | } 182 | 183 | inline void itohex(std::string& out, unsigned char x, bool upCase = true, bool withZero = true) 184 | { 185 | itoa_local::itohexLocal(out, x, upCase, withZero); 186 | } 187 | 188 | inline void itohex(std::string& out, unsigned short x, bool upCase = true, bool withZero = true) 189 | { 190 | itoa_local::itohexLocal(out, x, upCase, withZero); 191 | } 192 | 193 | inline void itohex(std::string& out, unsigned int x, bool upCase = true, bool withZero = true) 194 | { 195 | itoa_local::itohexLocal(out, x, upCase, withZero); 196 | } 197 | 198 | inline void itohex(std::string& out, unsigned long x, bool upCase = true, bool withZero = true) 199 | { 200 | itoa_local::itohexLocal(out, x, upCase, withZero); 201 | } 202 | 203 | inline void itohex(std::string& out, unsigned long long x, bool upCase = true, bool withZero = true) 204 | { 205 | itoa_local::itohexLocal(out, x, upCase, withZero); 206 | } 207 | 208 | template 209 | inline std::string itobin(T x, bool withZero = true) 210 | { 211 | std::string out; 212 | itoa_local::itobinLocal(out, x, withZero); 213 | return out; 214 | } 215 | 216 | inline void itobin(std::string& out, unsigned char x, bool withZero = true) 217 | { 218 | itoa_local::itobinLocal(out, x, withZero); 219 | } 220 | 221 | inline void itobin(std::string& out, unsigned short x, bool withZero = true) 222 | { 223 | itoa_local::itobinLocal(out, x, withZero); 224 | } 225 | 226 | inline void itobin(std::string& out, unsigned int x, bool withZero = true) 227 | { 228 | itoa_local::itobinLocal(out, x, withZero); 229 | } 230 | 231 | inline void itobin(std::string& out, unsigned long x, bool withZero = true) 232 | { 233 | itoa_local::itobinLocal(out, x, withZero); 234 | } 235 | 236 | inline void itobin(std::string& out, unsigned long long x, bool withZero = true) 237 | { 238 | itoa_local::itobinLocal(out, x, withZero); 239 | } 240 | 241 | template 242 | inline std::string itohex(T x, bool upCase = true, bool withZero = true) 243 | { 244 | std::string out; 245 | itohex(out, x, upCase, withZero); 246 | return out; 247 | } 248 | /** 249 | convert integer to string with zero padding 250 | @param x [in] int 251 | @param len [in] minimum lengh of string 252 | @param c [in] padding character 253 | @note 254 | itoa(12, 4) == "0012" 255 | itoa(1234, 4) == "1234" 256 | itoa(12345, 4) == "12345" 257 | itoa(-12, 4) == "-012" 258 | */ 259 | template 260 | inline std::string itoaWithZero(T x, size_t len, char c = '0') 261 | { 262 | std::string ret; 263 | itoa(ret, x); 264 | if (ret.size() < len) { 265 | std::string zero(len - ret.size(), c); 266 | if (x >= 0) { 267 | ret = zero + ret; 268 | } else { 269 | ret = "-" + zero + ret.substr(1); 270 | } 271 | } 272 | return ret; 273 | } 274 | 275 | } // cybozu 276 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/random_generator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief pseudrandom generator 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | 10 | #include 11 | #ifdef _WIN32 12 | #include 13 | #include 14 | #include 15 | #pragma comment (lib, "advapi32.lib") 16 | #include 17 | #else 18 | #include 19 | #include 20 | #endif 21 | 22 | namespace cybozu { 23 | 24 | class RandomGenerator { 25 | RandomGenerator(const RandomGenerator&); 26 | void operator=(const RandomGenerator&); 27 | public: 28 | uint32_t operator()() 29 | { 30 | return get32(); 31 | } 32 | uint32_t get32() 33 | { 34 | uint32_t ret; 35 | read(&ret, 1); 36 | return ret; 37 | } 38 | uint64_t get64() 39 | { 40 | uint64_t ret; 41 | read(&ret, 1); 42 | return ret; 43 | } 44 | #ifdef _WIN32 45 | RandomGenerator() 46 | : prov_(0) 47 | , pos_(bufSize) 48 | { 49 | DWORD flagTbl[] = { 0, CRYPT_NEWKEYSET }; 50 | for (int i = 0; i < 2; i++) { 51 | if (CryptAcquireContext(&prov_, NULL, NULL, PROV_RSA_FULL, flagTbl[i]) != 0) return; 52 | } 53 | throw cybozu::Exception("randomgenerator"); 54 | } 55 | void read_inner(void *buf, size_t byteSize) 56 | { 57 | if (CryptGenRandom(prov_, static_cast(byteSize), static_cast(buf)) == 0) { 58 | throw cybozu::Exception("randomgenerator:read") << byteSize; 59 | } 60 | } 61 | ~RandomGenerator() 62 | { 63 | if (prov_) { 64 | CryptReleaseContext(prov_, 0); 65 | } 66 | } 67 | /* 68 | fill buf[0..bufNum-1] with random data 69 | @note bufNum is not byte size 70 | */ 71 | template 72 | void read(T *buf, size_t bufNum) 73 | { 74 | cybozu::AutoLockCs al(cs_); 75 | const size_t byteSize = sizeof(T) * bufNum; 76 | if (byteSize > bufSize) { 77 | read_inner(buf, byteSize); 78 | } else { 79 | if (pos_ + byteSize > bufSize) { 80 | read_inner(buf_, bufSize); 81 | pos_ = 0; 82 | } 83 | memcpy(buf, buf_ + pos_, byteSize); 84 | pos_ += byteSize; 85 | } 86 | } 87 | private: 88 | HCRYPTPROV prov_; 89 | static const size_t bufSize = 1024; 90 | char buf_[bufSize]; 91 | size_t pos_; 92 | cybozu::CriticalSection cs_; 93 | #else 94 | RandomGenerator() 95 | : fp_(::fopen("/dev/urandom", "rb")) 96 | { 97 | if (!fp_) throw cybozu::Exception("randomgenerator"); 98 | } 99 | ~RandomGenerator() 100 | { 101 | if (fp_) ::fclose(fp_); 102 | } 103 | /* 104 | fill buf[0..bufNum-1] with random data 105 | @note bufNum is not byte size 106 | */ 107 | template 108 | void read(T *buf, size_t bufNum) 109 | { 110 | const size_t byteSize = sizeof(T) * bufNum; 111 | if (::fread(buf, 1, (int)byteSize, fp_) != byteSize) { 112 | throw cybozu::Exception("randomgenerator:read") << byteSize; 113 | } 114 | } 115 | #endif 116 | private: 117 | FILE *fp_; 118 | }; 119 | 120 | template 121 | void shuffle(T* v, size_t n, RG& rg) 122 | { 123 | if (n <= 1) return; 124 | for (size_t i = 0; i < n - 1; i++) { 125 | size_t r = i + size_t(rg.get64() % (n - i)); 126 | using namespace std; 127 | swap(v[i], v[r]); 128 | } 129 | } 130 | 131 | template 132 | void shuffle(V& v, RG& rg) 133 | { 134 | shuffle(v.data(), v.size(), rg); 135 | } 136 | 137 | } // cybozu 138 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/sha2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief SHA-256, SHA-512 class 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include // std::min 13 | #include 14 | #include 15 | 16 | namespace cybozu { 17 | 18 | namespace sha2_local { 19 | 20 | inline void uint32toHexStr(char *buf, const uint32_t *x, size_t n) 21 | { 22 | for (size_t i = 0; i < n; i++) { 23 | cybozu::itohex(buf + i * 8, 8, x[i], false); 24 | } 25 | } 26 | 27 | inline void uint64toHexStr(char *buf, const uint64_t *x, size_t n) 28 | { 29 | for (size_t i = 0; i < n; i++) { 30 | cybozu::itohex(buf + i * 16, 16, x[i], false); 31 | } 32 | } 33 | 34 | inline uint32_t rot32(uint32_t x, int s) 35 | { 36 | #ifdef _MSC_VER 37 | return _rotr(x, s); 38 | #else 39 | return (x >> s) | (x << (32 - s)); 40 | #endif 41 | } 42 | 43 | inline uint64_t rot64(uint64_t x, int s) 44 | { 45 | #ifdef _MSC_VER 46 | return _rotr64(x, s); 47 | #else 48 | return (x >> s) | (x << (64 - s)); 49 | #endif 50 | } 51 | 52 | } // cybozu::sha2_local 53 | 54 | class Sha256 { 55 | private: 56 | static const size_t blockSize_ = 64; 57 | static const size_t hSize_ = 8; 58 | uint64_t totalSize_; 59 | size_t roundBufSize_; 60 | char roundBuf_[blockSize_]; 61 | uint32_t h_[hSize_]; 62 | static const size_t outByteSize_ = hSize_ * sizeof(uint32_t); 63 | const uint32_t *k_; 64 | 65 | /** 66 | @param buf [in] buffer(64byte) 67 | */ 68 | void round(const char *buf) 69 | { 70 | using namespace sha2_local; 71 | uint32_t w[64]; 72 | for (int i = 0; i < 16; i++) { 73 | w[i] = cybozu::Get32bitAsBE(&buf[i * 4]); 74 | } 75 | for (int i = 16 ; i < 64; i++) { 76 | uint32_t t = w[i - 15]; 77 | uint32_t s0 = rot32(t, 7) ^ rot32(t, 18) ^ (t >> 3); 78 | t = w[i - 2]; 79 | uint32_t s1 = rot32(t, 17) ^ rot32(t, 19) ^ (t >> 10); 80 | w[i] = w[i - 16] + s0 + w[i - 7] + s1; 81 | } 82 | uint32_t a = h_[0]; 83 | uint32_t b = h_[1]; 84 | uint32_t c = h_[2]; 85 | uint32_t d = h_[3]; 86 | uint32_t e = h_[4]; 87 | uint32_t f = h_[5]; 88 | uint32_t g = h_[6]; 89 | uint32_t h = h_[7]; 90 | for (int i = 0; i < 64; i++) { 91 | uint32_t s1 = rot32(e, 6) ^ rot32(e, 11) ^ rot32(e, 25); 92 | uint32_t ch = g ^ (e & (f ^ g)); 93 | uint32_t t1 = h + s1 + ch + k_[i] + w[i]; 94 | uint32_t s0 = rot32(a, 2) ^ rot32(a, 13) ^ rot32(a, 22); 95 | uint32_t maj = ((a | b) & c) | (a & b); 96 | uint32_t t2 = s0 + maj; 97 | h = g; 98 | g = f; 99 | f = e; 100 | e = d + t1; 101 | d = c; 102 | c = b; 103 | b = a; 104 | a = t1 + t2; 105 | } 106 | h_[0] += a; 107 | h_[1] += b; 108 | h_[2] += c; 109 | h_[3] += d; 110 | h_[4] += e; 111 | h_[5] += f; 112 | h_[6] += g; 113 | h_[7] += h; 114 | totalSize_ += 64; 115 | } 116 | /* 117 | final phase 118 | */ 119 | void term(const char *buf, size_t bufSize) 120 | { 121 | assert(bufSize < blockSize_); 122 | const uint64_t totalSize = totalSize_ + bufSize; 123 | 124 | uint8_t last[blockSize_]; 125 | memcpy(last, buf, bufSize); 126 | memset(&last[bufSize], 0, blockSize_ - bufSize); 127 | last[bufSize] = uint8_t(0x80); /* top bit = 1 */ 128 | if (bufSize >= blockSize_ - 8) { 129 | round(reinterpret_cast(last)); 130 | memset(last, 0, sizeof(last)); // clear stack 131 | } 132 | cybozu::Set32bitAsBE(&last[56], uint32_t(totalSize >> 29)); 133 | cybozu::Set32bitAsBE(&last[60], uint32_t(totalSize * 8)); 134 | round(reinterpret_cast(last)); 135 | } 136 | public: 137 | Sha256() 138 | { 139 | clear(); 140 | } 141 | Sha256(const void *buf, size_t bufSize) 142 | { 143 | clear(); 144 | digest(buf, bufSize); 145 | } 146 | void clear() 147 | { 148 | static const uint32_t kTbl[] = { 149 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 150 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 151 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 152 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 153 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 154 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 155 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 156 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 157 | }; 158 | k_ = kTbl; 159 | totalSize_ = 0; 160 | roundBufSize_ = 0; 161 | h_[0] = 0x6a09e667; 162 | h_[1] = 0xbb67ae85; 163 | h_[2] = 0x3c6ef372; 164 | h_[3] = 0xa54ff53a; 165 | h_[4] = 0x510e527f; 166 | h_[5] = 0x9b05688c; 167 | h_[6] = 0x1f83d9ab; 168 | h_[7] = 0x5be0cd19; 169 | } 170 | void update(const void *buf_, size_t bufSize) 171 | { 172 | const char *buf = reinterpret_cast(buf_); 173 | if (bufSize == 0) return; 174 | if (roundBufSize_ > 0) { 175 | size_t size = (std::min)(blockSize_ - roundBufSize_, bufSize); 176 | memcpy(roundBuf_ + roundBufSize_, buf, size); 177 | roundBufSize_ += size; 178 | buf += size; 179 | bufSize -= size; 180 | } 181 | if (roundBufSize_ == blockSize_) { 182 | round(roundBuf_); 183 | roundBufSize_ = 0; 184 | } 185 | while (bufSize >= blockSize_) { 186 | assert(roundBufSize_ == 0); 187 | round(buf); 188 | buf += blockSize_; 189 | bufSize -= blockSize_; 190 | } 191 | if (bufSize > 0) { 192 | assert(bufSize < blockSize_); 193 | assert(roundBufSize_ == 0); 194 | memcpy(roundBuf_, buf, bufSize); 195 | roundBufSize_ = bufSize; 196 | } 197 | assert(roundBufSize_ < blockSize_); 198 | } 199 | void update(const std::string& buf) 200 | { 201 | update(buf.c_str(), buf.size()); 202 | } 203 | void digest(const void *buf, size_t bufSize) 204 | { 205 | update(buf, bufSize); 206 | term(roundBuf_, roundBufSize_); 207 | } 208 | void digest(const std::string& str = "") 209 | { 210 | digest(str.c_str(), str.size()); 211 | } 212 | void get(void *out) const 213 | { 214 | char *p = reinterpret_cast(out); 215 | for (size_t i = 0; i < hSize_; i++) { 216 | cybozu::Set32bitAsBE(&p[i * sizeof(h_[0])], h_[i]); 217 | } 218 | } 219 | std::string get() const 220 | { 221 | char out[outByteSize_]; 222 | get(out); 223 | return std::string(out, sizeof(out)); 224 | } 225 | std::string toHexStr() const 226 | { 227 | char buf[outByteSize_ * 2]; 228 | sha2_local::uint32toHexStr(buf, h_, hSize_); 229 | return std::string(buf, sizeof(buf)); 230 | } 231 | }; 232 | 233 | class Sha512 { 234 | private: 235 | static const size_t blockSize_ = 128; 236 | static const size_t hSize_ = 8; 237 | uint64_t totalSize_; 238 | size_t roundBufSize_; 239 | char roundBuf_[blockSize_]; 240 | uint64_t h_[hSize_]; 241 | static const size_t outByteSize_ = hSize_ * sizeof(uint64_t); 242 | const uint64_t *k_; 243 | 244 | template 245 | void round1(uint64_t *S, const uint64_t *w, size_t i) 246 | { 247 | using namespace sha2_local; 248 | uint64_t& a = S[i0]; 249 | uint64_t& b = S[i1]; 250 | uint64_t& c = S[i2]; 251 | uint64_t& d = S[i3]; 252 | uint64_t& e = S[i4]; 253 | uint64_t& f = S[i5]; 254 | uint64_t& g = S[i6]; 255 | uint64_t& h = S[i7]; 256 | 257 | uint64_t s1 = rot64(e, 14) ^ rot64(e, 18) ^ rot64(e, 41); 258 | uint64_t ch = g ^ (e & (f ^ g)); 259 | uint64_t t0 = h + s1 + ch + k_[i] + w[i]; 260 | uint64_t s0 = rot64(a, 28) ^ rot64(a, 34) ^ rot64(a, 39); 261 | uint64_t maj = ((a | b) & c) | (a & b); 262 | uint64_t t1 = s0 + maj; 263 | d += t0; 264 | h = t0 + t1; 265 | } 266 | /** 267 | @param buf [in] buffer(64byte) 268 | */ 269 | void round(const char *buf) 270 | { 271 | using namespace sha2_local; 272 | uint64_t w[80]; 273 | for (int i = 0; i < 16; i++) { 274 | w[i] = cybozu::Get64bitAsBE(&buf[i * 8]); 275 | } 276 | for (int i = 16 ; i < 80; i++) { 277 | uint64_t t = w[i - 15]; 278 | uint64_t s0 = rot64(t, 1) ^ rot64(t, 8) ^ (t >> 7); 279 | t = w[i - 2]; 280 | uint64_t s1 = rot64(t, 19) ^ rot64(t, 61) ^ (t >> 6); 281 | w[i] = w[i - 16] + s0 + w[i - 7] + s1; 282 | } 283 | uint64_t s[8]; 284 | for (int i = 0; i < 8; i++) { 285 | s[i] = h_[i]; 286 | } 287 | for (int i = 0; i < 80; i += 8) { 288 | round1<0, 1, 2, 3, 4, 5, 6, 7>(s, w, i + 0); 289 | round1<7, 0, 1, 2, 3, 4, 5, 6>(s, w, i + 1); 290 | round1<6, 7, 0, 1, 2, 3, 4, 5>(s, w, i + 2); 291 | round1<5, 6, 7, 0, 1, 2, 3, 4>(s, w, i + 3); 292 | round1<4, 5, 6, 7, 0, 1, 2, 3>(s, w, i + 4); 293 | round1<3, 4, 5, 6, 7, 0, 1, 2>(s, w, i + 5); 294 | round1<2, 3, 4, 5, 6, 7, 0, 1>(s, w, i + 6); 295 | round1<1, 2, 3, 4, 5, 6, 7, 0>(s, w, i + 7); 296 | } 297 | for (int i = 0; i < 8; i++) { 298 | h_[i] += s[i]; 299 | } 300 | totalSize_ += blockSize_; 301 | } 302 | /* 303 | final phase 304 | */ 305 | void term(const char *buf, size_t bufSize) 306 | { 307 | assert(bufSize < blockSize_); 308 | const uint64_t totalSize = totalSize_ + bufSize; 309 | 310 | uint8_t last[blockSize_]; 311 | memcpy(last, buf, bufSize); 312 | memset(&last[bufSize], 0, blockSize_ - bufSize); 313 | last[bufSize] = uint8_t(0x80); /* top bit = 1 */ 314 | if (bufSize >= blockSize_ - 16) { 315 | round(reinterpret_cast(last)); 316 | memset(last, 0, sizeof(last)); // clear stack 317 | } 318 | cybozu::Set64bitAsBE(&last[blockSize_ - 8], totalSize * 8); 319 | round(reinterpret_cast(last)); 320 | } 321 | public: 322 | Sha512() 323 | { 324 | clear(); 325 | } 326 | Sha512(const void *buf, size_t bufSize) 327 | { 328 | clear(); 329 | digest(buf, bufSize); 330 | } 331 | void clear() 332 | { 333 | static const uint64_t kTbl[] = { 334 | 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 335 | 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 336 | 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 337 | 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 338 | 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 0x983e5152ee66dfabULL, 339 | 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 340 | 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 341 | 0x53380d139d95b3dfULL, 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 342 | 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, 343 | 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 344 | 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 345 | 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 346 | 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 347 | 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 348 | 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 349 | 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL 350 | }; 351 | k_ = kTbl; 352 | totalSize_ = 0; 353 | roundBufSize_ = 0; 354 | h_[0] = 0x6a09e667f3bcc908ull; 355 | h_[1] = 0xbb67ae8584caa73bull; 356 | h_[2] = 0x3c6ef372fe94f82bull; 357 | h_[3] = 0xa54ff53a5f1d36f1ull; 358 | h_[4] = 0x510e527fade682d1ull; 359 | h_[5] = 0x9b05688c2b3e6c1full; 360 | h_[6] = 0x1f83d9abfb41bd6bull; 361 | h_[7] = 0x5be0cd19137e2179ull; 362 | } 363 | void update(const void *buf_, size_t bufSize) 364 | { 365 | const char *buf = reinterpret_cast(buf_); 366 | if (bufSize == 0) return; 367 | if (roundBufSize_ > 0) { 368 | size_t size = (std::min)(blockSize_ - roundBufSize_, bufSize); 369 | memcpy(roundBuf_ + roundBufSize_, buf, size); 370 | roundBufSize_ += size; 371 | buf += size; 372 | bufSize -= size; 373 | } 374 | if (roundBufSize_ == blockSize_) { 375 | round(roundBuf_); 376 | roundBufSize_ = 0; 377 | } 378 | while (bufSize >= blockSize_) { 379 | assert(roundBufSize_ == 0); 380 | round(buf); 381 | buf += blockSize_; 382 | bufSize -= blockSize_; 383 | } 384 | if (bufSize > 0) { 385 | assert(bufSize < blockSize_); 386 | assert(roundBufSize_ == 0); 387 | memcpy(roundBuf_, buf, bufSize); 388 | roundBufSize_ = bufSize; 389 | } 390 | assert(roundBufSize_ < blockSize_); 391 | } 392 | void update(const std::string& buf) 393 | { 394 | update(buf.c_str(), buf.size()); 395 | } 396 | void digest(const void *buf, size_t bufSize) 397 | { 398 | update(buf, bufSize); 399 | term(roundBuf_, roundBufSize_); 400 | } 401 | void digest(const std::string& str = "") 402 | { 403 | digest(str.c_str(), str.size()); 404 | } 405 | void get(void *out) const 406 | { 407 | char *p = reinterpret_cast(out); 408 | for (size_t i = 0; i < hSize_; i++) { 409 | cybozu::Set64bitAsBE(&p[i * sizeof(h_[0])], h_[i]); 410 | } 411 | } 412 | std::string get() const 413 | { 414 | char out[outByteSize_]; 415 | get(out); 416 | return std::string(out, sizeof(out)); 417 | } 418 | std::string toHexStr() const 419 | { 420 | char buf[outByteSize_ * 2]; 421 | sha2_local::uint64toHexStr(buf, h_, hSize_); 422 | return std::string(buf, sizeof(buf)); 423 | } 424 | }; 425 | 426 | } // cybozu 427 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/test.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief unit test class 5 | 6 | Copyright (C) 2008 Cybozu Labs, Inc., all rights reserved. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #if defined(_MSC_VER) && (MSC_VER <= 1500) 16 | #include 17 | #else 18 | #include 19 | #endif 20 | 21 | namespace cybozu { namespace test { 22 | 23 | class AutoRun { 24 | typedef void (*Func)(); 25 | typedef std::list > UnitTestList; 26 | public: 27 | AutoRun() 28 | : init_(0) 29 | , term_(0) 30 | , okCount_(0) 31 | , ngCount_(0) 32 | , exceptionCount_(0) 33 | { 34 | } 35 | void setup(Func init, Func term) 36 | { 37 | init_ = init; 38 | term_ = term; 39 | } 40 | void append(const char *name, Func func) 41 | { 42 | list_.push_back(std::make_pair(name, func)); 43 | } 44 | void set(bool isOK) 45 | { 46 | if (isOK) { 47 | okCount_++; 48 | } else { 49 | ngCount_++; 50 | } 51 | } 52 | std::string getBaseName(const std::string& name) const 53 | { 54 | #ifdef _WIN32 55 | const char sep = '\\'; 56 | #else 57 | const char sep = '/'; 58 | #endif 59 | size_t pos = name.find_last_of(sep); 60 | std::string ret = name.substr(pos + 1); 61 | pos = ret.find('.'); 62 | return ret.substr(0, pos); 63 | } 64 | int run(int, char *argv[]) 65 | { 66 | std::string msg; 67 | try { 68 | if (init_) init_(); 69 | for (UnitTestList::const_iterator i = list_.begin(), ie = list_.end(); i != ie; ++i) { 70 | std::cout << "ctest:module=" << i->first << std::endl; 71 | try { 72 | (i->second)(); 73 | } catch (std::exception& e) { 74 | exceptionCount_++; 75 | std::cout << "ctest: " << i->first << " is stopped by exception " << e.what() << std::endl; 76 | } catch (...) { 77 | exceptionCount_++; 78 | std::cout << "ctest: " << i->first << " is stopped by unknown exception" << std::endl; 79 | } 80 | } 81 | if (term_) term_(); 82 | } catch (std::exception& e) { 83 | msg = std::string("ctest:err:") + e.what(); 84 | } catch (...) { 85 | msg = "ctest:err: catch unknown exception"; 86 | } 87 | fflush(stdout); 88 | if (msg.empty()) { 89 | int total = okCount_ + ngCount_ + exceptionCount_; 90 | std::cout << "ctest:name=" << getBaseName(*argv) 91 | << ", module=" << list_.size() 92 | << ", total=" << total 93 | << ", ok=" << okCount_ 94 | << ", ng=" << ngCount_ 95 | << ", exception=" << exceptionCount_ << std::endl; 96 | return total > 0 ? 1 : 0; 97 | } else { 98 | std::cout << msg << std::endl; 99 | return 1; 100 | } 101 | } 102 | static inline AutoRun& getInstance() 103 | { 104 | static AutoRun instance; 105 | return instance; 106 | } 107 | private: 108 | Func init_; 109 | Func term_; 110 | int okCount_; 111 | int ngCount_; 112 | int exceptionCount_; 113 | UnitTestList list_; 114 | }; 115 | 116 | static AutoRun& autoRun = AutoRun::getInstance(); 117 | 118 | inline void test(bool ret, const std::string& msg, const std::string& param, const char *file, int line) 119 | { 120 | autoRun.set(ret); 121 | if (!ret) { 122 | printf("%s(%d):ctest:%s(%s);\n", file, line, msg.c_str(), param.c_str()); 123 | } 124 | } 125 | 126 | template 127 | bool isEqual(const T& lhs, const U& rhs) 128 | { 129 | return lhs == rhs; 130 | } 131 | 132 | // avoid warning of comparision of integers of different signs 133 | inline bool isEqual(size_t lhs, int rhs) 134 | { 135 | return lhs == size_t(rhs); 136 | } 137 | inline bool isEqual(int lhs, size_t rhs) 138 | { 139 | return size_t(lhs) == rhs; 140 | } 141 | inline bool isEqual(const char *lhs, const char *rhs) 142 | { 143 | return strcmp(lhs, rhs) == 0; 144 | } 145 | inline bool isEqual(char *lhs, const char *rhs) 146 | { 147 | return strcmp(lhs, rhs) == 0; 148 | } 149 | inline bool isEqual(const char *lhs, char *rhs) 150 | { 151 | return strcmp(lhs, rhs) == 0; 152 | } 153 | inline bool isEqual(char *lhs, char *rhs) 154 | { 155 | return strcmp(lhs, rhs) == 0; 156 | } 157 | // avoid to compare float directly 158 | inline bool isEqual(float lhs, float rhs) 159 | { 160 | union fi { 161 | float f; 162 | uint32_t i; 163 | } lfi, rfi; 164 | lfi.f = lhs; 165 | rfi.f = rhs; 166 | return lfi.i == rfi.i; 167 | } 168 | // avoid to compare double directly 169 | inline bool isEqual(double lhs, double rhs) 170 | { 171 | union di { 172 | double d; 173 | uint64_t i; 174 | } ldi, rdi; 175 | ldi.d = lhs; 176 | rdi.d = rhs; 177 | return ldi.i == rdi.i; 178 | } 179 | 180 | } } // cybozu::test 181 | 182 | #ifndef CYBOZU_TEST_DISABLE_AUTO_RUN 183 | int main(int argc, char *argv[]) 184 | { 185 | return cybozu::test::autoRun.run(argc, argv); 186 | } 187 | #endif 188 | 189 | /** 190 | alert if !x 191 | @param x [in] 192 | */ 193 | #define CYBOZU_TEST_ASSERT(x) cybozu::test::test(!!(x), "CYBOZU_TEST_ASSERT", #x, __FILE__, __LINE__) 194 | 195 | /** 196 | alert if x != y 197 | @param x [in] 198 | @param y [in] 199 | */ 200 | #define CYBOZU_TEST_EQUAL(x, y) { \ 201 | bool _cybozu_eq = cybozu::test::isEqual(x, y); \ 202 | cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL", #x ", " #y, __FILE__, __LINE__); \ 203 | if (!_cybozu_eq) { \ 204 | std::cout << "ctest: lhs=" << (x) << std::endl; \ 205 | std::cout << "ctest: rhs=" << (y) << std::endl; \ 206 | } \ 207 | } 208 | /** 209 | alert if fabs(x, y) >= eps 210 | @param x [in] 211 | @param y [in] 212 | */ 213 | #define CYBOZU_TEST_NEAR(x, y, eps) { \ 214 | bool _cybozu_isNear = fabs((x) - (y)) < eps; \ 215 | cybozu::test::test(_cybozu_isNear, "CYBOZU_TEST_NEAR", #x ", " #y, __FILE__, __LINE__); \ 216 | if (!_cybozu_isNear) { \ 217 | std::cout << "ctest: lhs=" << (x) << std::endl; \ 218 | std::cout << "ctest: rhs=" << (y) << std::endl; \ 219 | } \ 220 | } 221 | 222 | #define CYBOZU_TEST_EQUAL_POINTER(x, y) { \ 223 | bool _cybozu_eq = x == y; \ 224 | cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_POINTER", #x ", " #y, __FILE__, __LINE__); \ 225 | if (!_cybozu_eq) { \ 226 | std::cout << "ctest: lhs=" << static_cast(x) << std::endl; \ 227 | std::cout << "ctest: rhs=" << static_cast(y) << std::endl; \ 228 | } \ 229 | } 230 | /** 231 | alert if x[] != y[] 232 | @param x [in] 233 | @param y [in] 234 | @param n [in] 235 | */ 236 | #define CYBOZU_TEST_EQUAL_ARRAY(x, y, n) { \ 237 | for (size_t _cybozu_test_i = 0, _cybozu_ie = (size_t)(n); _cybozu_test_i < _cybozu_ie; _cybozu_test_i++) { \ 238 | bool _cybozu_eq = cybozu::test::isEqual((x)[_cybozu_test_i], (y)[_cybozu_test_i]); \ 239 | cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_ARRAY", #x ", " #y ", " #n, __FILE__, __LINE__); \ 240 | if (!_cybozu_eq) { \ 241 | std::cout << "ctest: i=" << _cybozu_test_i << std::endl; \ 242 | std::cout << "ctest: lhs=" << (x)[_cybozu_test_i] << std::endl; \ 243 | std::cout << "ctest: rhs=" << (y)[_cybozu_test_i] << std::endl; \ 244 | } \ 245 | } \ 246 | } 247 | 248 | /** 249 | always alert 250 | @param msg [in] 251 | */ 252 | #define CYBOZU_TEST_FAIL(msg) cybozu::test::test(false, "CYBOZU_TEST_FAIL", msg, __FILE__, __LINE__) 253 | 254 | /** 255 | verify message in exception 256 | */ 257 | #define CYBOZU_TEST_EXCEPTION_MESSAGE(statement, Exception, msg) \ 258 | { \ 259 | int _cybozu_ret = 0; \ 260 | std::string _cybozu_errMsg; \ 261 | try { \ 262 | statement; \ 263 | _cybozu_ret = 1; \ 264 | } catch (const Exception& _cybozu_e) { \ 265 | _cybozu_errMsg = _cybozu_e.what(); \ 266 | if (_cybozu_errMsg.find(msg) == std::string::npos) { \ 267 | _cybozu_ret = 2; \ 268 | } \ 269 | } catch (...) { \ 270 | _cybozu_ret = 3; \ 271 | } \ 272 | if (_cybozu_ret) { \ 273 | cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION_MESSAGE", #statement ", " #Exception ", " #msg, __FILE__, __LINE__); \ 274 | if (_cybozu_ret == 1) { \ 275 | std::cout << "ctest: no exception" << std::endl; \ 276 | } else if (_cybozu_ret == 2) { \ 277 | std::cout << "ctest: bad exception msg:" << _cybozu_errMsg << std::endl; \ 278 | } else { \ 279 | std::cout << "ctest: unexpected exception" << std::endl; \ 280 | } \ 281 | } else { \ 282 | cybozu::test::autoRun.set(true); \ 283 | } \ 284 | } 285 | 286 | #define CYBOZU_TEST_EXCEPTION(statement, Exception) \ 287 | { \ 288 | int _cybozu_ret = 0; \ 289 | try { \ 290 | statement; \ 291 | _cybozu_ret = 1; \ 292 | } catch (const Exception&) { \ 293 | } catch (...) { \ 294 | _cybozu_ret = 2; \ 295 | } \ 296 | if (_cybozu_ret) { \ 297 | cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION", #statement ", " #Exception, __FILE__, __LINE__); \ 298 | if (_cybozu_ret == 1) { \ 299 | std::cout << "ctest: no exception" << std::endl; \ 300 | } else { \ 301 | std::cout << "ctest: unexpected exception" << std::endl; \ 302 | } \ 303 | } else { \ 304 | cybozu::test::autoRun.set(true); \ 305 | } \ 306 | } 307 | 308 | /** 309 | verify statement does not throw 310 | */ 311 | #define CYBOZU_TEST_NO_EXCEPTION(statement) \ 312 | try { \ 313 | statement; \ 314 | cybozu::test::autoRun.set(true); \ 315 | } catch (...) { \ 316 | cybozu::test::test(false, "CYBOZU_TEST_NO_EXCEPTION", #statement, __FILE__, __LINE__); \ 317 | } 318 | 319 | /** 320 | append auto unit test 321 | @param name [in] module name 322 | */ 323 | #define CYBOZU_TEST_AUTO(name) \ 324 | void cybozu_test_ ## name(); \ 325 | struct cybozu_test_local_ ## name { \ 326 | cybozu_test_local_ ## name() \ 327 | { \ 328 | cybozu::test::autoRun.append(#name, cybozu_test_ ## name); \ 329 | } \ 330 | } cybozu_test_local_instance_ ## name; \ 331 | void cybozu_test_ ## name() 332 | 333 | /** 334 | append auto unit test with fixture 335 | @param name [in] module name 336 | */ 337 | #define CYBOZU_TEST_AUTO_WITH_FIXTURE(name, Fixture) \ 338 | void cybozu_test_ ## name(); \ 339 | void cybozu_test_real_ ## name() \ 340 | { \ 341 | Fixture f; \ 342 | cybozu_test_ ## name(); \ 343 | } \ 344 | struct cybozu_test_local_ ## name { \ 345 | cybozu_test_local_ ## name() \ 346 | { \ 347 | cybozu::test::autoRun.append(#name, cybozu_test_real_ ## name); \ 348 | } \ 349 | } cybozu_test_local_instance_ ## name; \ 350 | void cybozu_test_ ## name() 351 | 352 | /** 353 | setup fixture 354 | @param Fixture [in] class name of fixture 355 | @note cstr of Fixture is called before test and dstr of Fixture is called after test 356 | */ 357 | #define CYBOZU_TEST_SETUP_FIXTURE(Fixture) \ 358 | Fixture *cybozu_test_local_fixture; \ 359 | void cybozu_test_local_init() \ 360 | { \ 361 | cybozu_test_local_fixture = new Fixture(); \ 362 | } \ 363 | void cybozu_test_local_term() \ 364 | { \ 365 | delete cybozu_test_local_fixture; \ 366 | } \ 367 | struct cybozu_test_local_fixture_setup_ { \ 368 | cybozu_test_local_fixture_setup_() \ 369 | { \ 370 | cybozu::test::autoRun.setup(cybozu_test_local_init, cybozu_test_local_term); \ 371 | } \ 372 | } cybozu_test_local_fixture_setup_instance_; 373 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/unordered_map.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef CYBOZU_USE_BOOST 6 | #include 7 | #elif (CYBOZU_CPP_VERSION == CYBOZU_CPP_VERSION_CPP11) || (defined __APPLE__) 8 | #include 9 | #elif (CYBOZU_CPP_VERSION == CYBOZU_CPP_VERSION_TR1) 10 | #include 11 | #include 12 | #endif 13 | 14 | -------------------------------------------------------------------------------- /cybozulib/include/cybozu/xorshift.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief XorShift 5 | 6 | Copyright (C) 2007 Cybozu Labs, Inc., all rights reserved. 7 | @author MITSUNARI Shigeo 8 | */ 9 | #include 10 | 11 | namespace cybozu { 12 | 13 | class XorShift { 14 | uint32_t x_, y_, z_, w_; 15 | public: 16 | explicit XorShift(uint32_t x = 0, uint32_t y = 0, uint32_t z = 0, uint32_t w = 0) 17 | { 18 | init(x, y, z, w); 19 | } 20 | void init(uint32_t x = 0, uint32_t y = 0, uint32_t z = 0, uint32_t w = 0) 21 | { 22 | x_ = x ? x : 123456789; 23 | y_ = y ? y : 362436069; 24 | z_ = z ? z : 521288629; 25 | w_ = w ? w : 88675123; 26 | } 27 | uint32_t get32() 28 | { 29 | unsigned int t = x_ ^ (x_ << 11); 30 | x_ = y_; y_ = z_; z_ = w_; 31 | return w_ = (w_ ^ (w_ >> 19)) ^ (t ^ (t >> 8)); 32 | } 33 | uint32_t operator()() { return get32(); } 34 | uint64_t get64() 35 | { 36 | uint32_t a = get32(); 37 | uint32_t b = get32(); 38 | return (uint64_t(a) << 32) | b; 39 | } 40 | template 41 | void read(T *x, size_t n) 42 | { 43 | const size_t size = sizeof(T) * n; 44 | uint8_t *p8 = static_cast(x); 45 | for (size_t i = 0; i < size; i++) { 46 | p8[i] = static_cast(get32()); 47 | } 48 | } 49 | void read(uint32_t *x, size_t n) 50 | { 51 | for (size_t i = 0; i < n; i++) { 52 | x[i] = get32(); 53 | } 54 | } 55 | void read(uint64_t *x, size_t n) 56 | { 57 | for (size_t i = 0; i < n; i++) { 58 | x[i] = get64(); 59 | } 60 | } 61 | }; 62 | 63 | // see http://xorshift.di.unimi.it/xorshift128plus.c 64 | class XorShift128Plus { 65 | uint64_t s_[2]; 66 | static const uint64_t seed0 = 123456789; 67 | static const uint64_t seed1 = 987654321; 68 | public: 69 | explicit XorShift128Plus(uint64_t s0 = seed0, uint64_t s1 = seed1) 70 | { 71 | init(s0, s1); 72 | } 73 | void init(uint64_t s0 = seed0, uint64_t s1 = seed1) 74 | { 75 | s_[0] = s0; 76 | s_[1] = s1; 77 | } 78 | uint32_t get32() 79 | { 80 | return static_cast(get64()); 81 | } 82 | uint64_t operator()() { return get64(); } 83 | uint64_t get64() 84 | { 85 | uint64_t s1 = s_[0]; 86 | const uint64_t s0 = s_[1]; 87 | s_[0] = s0; 88 | s1 ^= s1 << 23; 89 | s_[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5); 90 | return s_[1] + s0; 91 | } 92 | template 93 | void read(T *x, size_t n) 94 | { 95 | const size_t size = sizeof(T) * n; 96 | uint8_t *p8 = static_cast(x); 97 | for (size_t i = 0; i < size; i++) { 98 | p8[i] = static_cast(get32()); 99 | } 100 | } 101 | void read(uint32_t *x, size_t n) 102 | { 103 | for (size_t i = 0; i < n; i++) { 104 | x[i] = get32(); 105 | } 106 | } 107 | void read(uint64_t *x, size_t n) 108 | { 109 | for (size_t i = 0; i < n; i++) { 110 | x[i] = get64(); 111 | } 112 | } 113 | }; 114 | 115 | // see http://xoroshiro.di.unimi.it/xoroshiro128plus.c 116 | class Xoroshiro128Plus { 117 | uint64_t s_[2]; 118 | static const uint64_t seed0 = 123456789; 119 | static const uint64_t seed1 = 987654321; 120 | uint64_t rotl(uint64_t x, unsigned int k) const 121 | { 122 | return (x << k) | (x >> (64 - k)); 123 | } 124 | public: 125 | explicit Xoroshiro128Plus(uint64_t s0 = seed0, uint64_t s1 = seed1) 126 | { 127 | init(s0, s1); 128 | } 129 | void init(uint64_t s0 = seed0, uint64_t s1 = seed1) 130 | { 131 | s_[0] = s0; 132 | s_[1] = s1; 133 | } 134 | uint32_t get32() 135 | { 136 | return static_cast(get64()); 137 | } 138 | uint64_t operator()() { return get64(); } 139 | uint64_t get64() 140 | { 141 | uint64_t s0 = s_[0]; 142 | uint64_t s1 = s_[1]; 143 | uint64_t result = s0 + s1; 144 | s1 ^= s0; 145 | s_[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); 146 | s_[1] = rotl(s1, 36); 147 | return result; 148 | } 149 | template 150 | void read(T *x, size_t n) 151 | { 152 | const size_t size = sizeof(T) * n; 153 | uint8_t *p8 = static_cast(x); 154 | for (size_t i = 0; i < size; i++) { 155 | p8[i] = static_cast(get32()); 156 | } 157 | } 158 | void read(uint32_t *x, size_t n) 159 | { 160 | for (size_t i = 0; i < n; i++) { 161 | x[i] = get32(); 162 | } 163 | } 164 | void read(uint64_t *x, size_t n) 165 | { 166 | for (size_t i = 0; i < n; i++) { 167 | x[i] = get64(); 168 | } 169 | } 170 | }; 171 | 172 | } // cybozu 173 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: 2 | with pkgs; let 3 | drv = import ./bn.nix { 4 | inherit make clang llvm gmpxx openssl; 5 | stdenv = clangStdenv; 6 | }; 7 | in 8 | drv 9 | -------------------------------------------------------------------------------- /license/cybozulib/COPYRIGHT: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2007-2012 Cybozu Labs, Inc. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | Neither the name of the Cybozu Labs, Inc. nor the names of its contributors may 14 | be used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /license/mcl/COPYRIGHT: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2015 MITSUNARI Shigeo 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | Neither the name of the copyright owner nor the names of its contributors may 14 | be used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | THE POSSIBILITY OF SUCH DAMAGE. 28 | ----------------------------------------------------------------------------- 29 | ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満た 30 | す場合に限り、再頒布および使用が許可されます。 31 | 32 | ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責条項 33 | を含めること。 34 | バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の著作 35 | 権表示、本条件一覧、および下記免責条項を含めること。 36 | 書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売促進 37 | に、著作権者の名前またはコントリビューターの名前を使用してはならない。 38 | 本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供さ 39 | れており、明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適合性 40 | に関する暗黙の保証も含め、またそれに限定されない、いかなる保証もありません。 41 | 著作権者もコントリビューターも、事由のいかんを問わず、 損害発生の原因いかんを 42 | 問わず、かつ責任の根拠が契約であるか厳格責任であるか(過失その他の)不法行為で 43 | あるかを問わず、仮にそのような損害が発生する可能性を知らされていたとしても、 44 | 本ソフトウェアの使用によって発生した(代替品または代用サービスの調達、使用の 45 | 喪失、データの喪失、利益の喪失、業務の中断も含め、またそれに限定されない)直接 46 | 損害、間接損害、偶発的な損害、特別損害、懲罰的損害、または結果損害について、 47 | 一切責任を負わないものとします。 48 | -------------------------------------------------------------------------------- /license/readme.md: -------------------------------------------------------------------------------- 1 | 2 | * [cybozulib](https://github.com/herumi/cybozulib) 3 | * [xbyak](https://github.com/herumi/xbyak) 4 | * [mcl](https://github.com/herumi/mcl) 5 | * [bls](https://github.com/herumi/bls) 6 | -------------------------------------------------------------------------------- /license/xbyak/COPYRIGHT: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2007 MITSUNARI Shigeo 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | Neither the name of the copyright owner nor the names of its contributors may 14 | be used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 | THE POSSIBILITY OF SUCH DAMAGE. 28 | ----------------------------------------------------------------------------- 29 | ソースコード形式かバイナリ形式か、変更するかしないかを問わず、以下の条件を満た 30 | す場合に限り、再頒布および使用が許可されます。 31 | 32 | ソースコードを再頒布する場合、上記の著作権表示、本条件一覧、および下記免責条項 33 | を含めること。 34 | バイナリ形式で再頒布する場合、頒布物に付属のドキュメント等の資料に、上記の著作 35 | 権表示、本条件一覧、および下記免責条項を含めること。 36 | 書面による特別の許可なしに、本ソフトウェアから派生した製品の宣伝または販売促進 37 | に、著作権者の名前またはコントリビューターの名前を使用してはならない。 38 | 本ソフトウェアは、著作権者およびコントリビューターによって「現状のまま」提供さ 39 | れており、明示黙示を問わず、商業的な使用可能性、および特定の目的に対する適合性 40 | に関する暗黙の保証も含め、またそれに限定されない、いかなる保証もありません。 41 | 著作権者もコントリビューターも、事由のいかんを問わず、 損害発生の原因いかんを 42 | 問わず、かつ責任の根拠が契約であるか厳格責任であるか(過失その他の)不法行為で 43 | あるかを問わず、仮にそのような損害が発生する可能性を知らされていたとしても、 44 | 本ソフトウェアの使用によって発生した(代替品または代用サービスの調達、使用の 45 | 喪失、データの喪失、利益の喪失、業務の中断も含め、またそれに限定されない)直接 46 | 損害、間接損害、偶発的な損害、特別損害、懲罰的損害、または結果損害について、 47 | 一切責任を負わないものとします。 48 | -------------------------------------------------------------------------------- /mcl/Makefile: -------------------------------------------------------------------------------- 1 | include common.mk 2 | LIB_DIR=lib 3 | OBJ_DIR=obj 4 | EXE_DIR=bin 5 | SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp 6 | 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 7 | TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp 8 | ifeq ($(CPU),x86-64) 9 | MCL_USE_XBYAK?=1 10 | TEST_SRC+=mont_fp_test.cpp sq_test.cpp 11 | ifeq ($(USE_LOW_ASM),1) 12 | TEST_SRC+=low_test.cpp 13 | endif 14 | ifeq ($(MCL_USE_XBYAK),1) 15 | TEST_SRC+=fp_generator_test.cpp 16 | endif 17 | endif 18 | SAMPLE_SRC=bench.cpp ecdh.cpp random.cpp rawbench.cpp vote.cpp pairing.cpp large.cpp tri-dh.cpp bls_sig.cpp pairing_c.c she_smpl.cpp 19 | 20 | ifneq ($(MCL_MAX_BIT_SIZE),) 21 | CFLAGS+=-DMCL_MAX_BIT_SIZE=$(MCL_MAX_BIT_SIZE) 22 | endif 23 | ifeq ($(MCL_USE_XBYAK),0) 24 | CFLAGS+=-DMCL_DONT_USE_XBYAK 25 | endif 26 | SHARE_BASENAME_SUF?= 27 | ################################################################## 28 | MCL_LIB=$(LIB_DIR)/libmcl.a 29 | MCL_SNAME=mcl$(SHARE_BASENAME_SUF) 30 | BN256_SNAME=mclbn256$(SHARE_BASENAME_SUF) 31 | BN384_SNAME=mclbn384$(SHARE_BASENAME_SUF) 32 | MCL_SLIB=$(LIB_DIR)/lib$(MCL_SNAME).$(LIB_SUF) 33 | BN256_LIB=$(LIB_DIR)/libmclbn256.a 34 | BN256_SLIB=$(LIB_DIR)/lib$(BN256_SNAME).$(LIB_SUF) 35 | BN384_LIB=$(LIB_DIR)/libmclbn384.a 36 | BN384_SLIB=$(LIB_DIR)/lib$(BN384_SNAME).$(LIB_SUF) 37 | all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) 38 | 39 | #LLVM_VER=-3.8 40 | LLVM_LLC=llc$(LLVM_VER) 41 | LLVM_OPT=opt$(LLVM_VER) 42 | LLVM_OPT_VERSION=$(shell $(LLVM_OPT) --version | awk '/version/ {print $$3}') 43 | GEN_EXE=src/gen 44 | # incompatibility between llvm 3.4 and the later version 45 | ifeq ($(shell expr $(LLVM_OPT_VERSION) \< 3.5.0),1) 46 | GEN_EXE_OPT=-old 47 | endif 48 | ifeq ($(OS),mac) 49 | ASM_SRC_PATH_NAME=src/asm/$(CPU)mac 50 | else 51 | ASM_SRC_PATH_NAME=src/asm/$(CPU) 52 | endif 53 | ifneq ($(CPU),) 54 | ASM_SRC=$(ASM_SRC_PATH_NAME).s 55 | endif 56 | ASM_OBJ=$(OBJ_DIR)/$(CPU).o 57 | LIB_OBJ=$(OBJ_DIR)/fp.o 58 | BN256_OBJ=$(OBJ_DIR)/bn_c256.o 59 | BN384_OBJ=$(OBJ_DIR)/bn_c384.o 60 | FUNC_LIST=src/func.list 61 | MCL_USE_LLVM?=1 62 | ifeq ($(MCL_USE_LLVM),1) 63 | CFLAGS+=-DMCL_USE_LLVM=1 64 | LIB_OBJ+=$(ASM_OBJ) 65 | endif 66 | LLVM_SRC=src/base$(BIT).ll 67 | 68 | # CPU is used for llvm 69 | # see $(LLVM_LLC) --version 70 | LLVM_FLAGS=-march=$(CPU) -relocation-model=pic #-misched=ilpmax 71 | LLVM_FLAGS+=-pre-RA-sched=list-ilp -max-sched-reorder=128 72 | 73 | #HAS_BMI2=$(shell cat "/proc/cpuinfo" | grep bmi2 >/dev/null && echo "1") 74 | #ifeq ($(HAS_BMI2),1) 75 | # LLVM_FLAGS+=-mattr=bmi2 76 | #endif 77 | 78 | ifeq ($(USE_LOW_ASM),1) 79 | LOW_ASM_OBJ=$(LOW_ASM_SRC:.asm=.o) 80 | LIB_OBJ+=$(LOW_ASM_OBJ) 81 | endif 82 | # special case for intel with bmi2 83 | ifeq ($(INTEL),1) 84 | LIB_OBJ+=$(OBJ_DIR)/$(CPU).bmi2.o 85 | endif 86 | 87 | ifeq ($(UPDATE_ASM),1) 88 | ASM_SRC_DEP=$(LLVM_SRC) 89 | ASM_BMI2_SRC_DEP=src/base$(BIT).bmi2.ll 90 | else 91 | ASM_SRC_DEP= 92 | ASM_BMI2_SRC_DEP= 93 | endif 94 | 95 | $(MCL_LIB): $(LIB_OBJ) 96 | $(AR) $@ $(LIB_OBJ) 97 | 98 | $(MCL_SLIB): $(LIB_OBJ) 99 | $(PRE)$(CXX) -o $@ $(LIB_OBJ) -shared $(LDFLAGS) 100 | 101 | $(BN256_LIB): $(BN256_OBJ) 102 | $(AR) $@ $(BN256_OBJ) 103 | 104 | ifeq ($(OS),mac) 105 | MAC_LDFLAGS+=-l$(MCL_SNAME) -L./lib 106 | endif 107 | $(BN256_SLIB): $(BN256_OBJ) $(MCL_SLIB) 108 | $(PRE)$(CXX) -o $@ $(BN256_OBJ) -shared $(LDFLAGS) $(MAC_LDFLAGS) 109 | 110 | $(BN384_LIB): $(BN384_OBJ) 111 | $(AR) $@ $(BN384_OBJ) 112 | 113 | $(BN384_SLIB): $(BN384_OBJ) $(MCL_SLIB) 114 | $(PRE)$(CXX) -o $@ $(BN384_OBJ) -shared $(LDFLAGS) $(MAC_LDFLAGS) 115 | 116 | $(ASM_OBJ): $(ASM_SRC) 117 | $(PRE)$(CXX) -c $< -o $@ $(CFLAGS) 118 | 119 | $(ASM_SRC): $(ASM_SRC_DEP) 120 | $(LLVM_OPT) -O3 -o - $< -march=$(CPU) | $(LLVM_LLC) -O3 -o $@ $(LLVM_FLAGS) 121 | 122 | $(LLVM_SRC): $(GEN_EXE) $(FUNC_LIST) 123 | $(GEN_EXE) $(GEN_EXE_OPT) -f $(FUNC_LIST) > $@ 124 | 125 | $(ASM_SRC_PATH_NAME).bmi2.s: $(ASM_BMI2_SRC_DEP) 126 | $(LLVM_OPT) -O3 -o - $< -march=$(CPU) | $(LLVM_LLC) -O3 -o $@ $(LLVM_FLAGS) -mattr=bmi2 127 | 128 | $(OBJ_DIR)/$(CPU).bmi2.o: $(ASM_SRC_PATH_NAME).bmi2.s 129 | $(PRE)$(CXX) -c $< -o $@ $(CFLAGS) 130 | 131 | src/base$(BIT).bmi2.ll: $(GEN_EXE) 132 | $(GEN_EXE) $(GEN_EXE_OPT) -f $(FUNC_LIST) -s bmi2 > $@ 133 | 134 | $(FUNC_LIST): $(LOW_ASM_SRC) 135 | ifeq ($(USE_LOW_ASM),1) 136 | $(shell awk '/global/ { print $$2}' $(LOW_ASM_SRC) > $(FUNC_LIST)) 137 | $(shell awk '/proc/ { print $$2}' $(LOW_ASM_SRC) >> $(FUNC_LIST)) 138 | else 139 | $(shell touch $(FUNC_LIST)) 140 | endif 141 | 142 | $(GEN_EXE): src/gen.cpp src/llvm_gen.hpp 143 | $(CXX) -o $@ $< $(CFLAGS) -O0 144 | 145 | asm: $(LLVM_SRC) 146 | $(LLVM_OPT) -O3 -o - $(LLVM_SRC) | $(LLVM_LLC) -O3 $(LLVM_FLAGS) -x86-asm-syntax=intel 147 | 148 | $(LOW_ASM_OBJ): $(LOW_ASM_SRC) 149 | $(ASM) $< 150 | 151 | ifeq ($(OS),mac) 152 | MAC_GO_LDFLAGS="-ldflags=-s" 153 | endif 154 | test_go256: $(MCL_SLIB) $(BN256_SLIB) 155 | cd ffi/go/mcl && env LD_RUN_PATH="../../../lib" CGO_CFLAGS="-I../../../include" CGO_LDFLAGS="-L../../../lib -l$(BN256_SNAME) -l$(MCL_SNAME) -lgmpxx -lgmp -lcrypto -lstdc++" go test $(MAC_GO_LDFLAGS) -tags bn256 . 156 | 157 | test_go384: $(MCL_SLIB) $(BN384_SLIB) 158 | cd ffi/go/mcl && env LD_RUN_PATH="../../../lib" CGO_CFLAGS="-I../../../include" CGO_LDFLAGS="-L../../../lib -l$(BN384_SNAME) -l$(MCL_SNAME) -lgmpxx -lgmp -lcrypto -lstdc++" go test $(MAC_GO_LDFLAGS) . 159 | 160 | test_go: 161 | $(MAKE) test_go256 162 | $(MAKE) test_go384 163 | 164 | ################################################################## 165 | 166 | VPATH=test sample src 167 | 168 | .SUFFIXES: .cpp .d .exe .c .o 169 | 170 | $(OBJ_DIR)/%.o: %.cpp 171 | $(PRE)$(CXX) $(CFLAGS) -c $< -o $@ -MMD -MP -MF $(@:.o=.d) 172 | 173 | $(OBJ_DIR)/%.o: %.c 174 | $(PRE)$(CC) $(CFLAGS) -c $< -o $@ -MMD -MP -MF $(@:.o=.d) 175 | 176 | $(EXE_DIR)/%.exe: $(OBJ_DIR)/%.o $(MCL_LIB) 177 | $(PRE)$(CXX) $< -o $@ $(MCL_LIB) $(LDFLAGS) 178 | 179 | $(EXE_DIR)/bn_c256_test.exe: $(OBJ_DIR)/bn_c256_test.o $(BN256_LIB) $(MCL_LIB) 180 | $(PRE)$(CXX) $< -o $@ $(BN256_LIB) $(MCL_LIB) $(LDFLAGS) 181 | 182 | $(EXE_DIR)/bn_c384_test.exe: $(OBJ_DIR)/bn_c384_test.o $(BN384_LIB) $(MCL_LIB) 183 | $(PRE)$(CXX) $< -o $@ $(BN384_LIB) $(MCL_LIB) $(LDFLAGS) 184 | 185 | $(EXE_DIR)/pairing_c.exe: $(OBJ_DIR)/pairing_c.o $(BN256_LIB) $(MCL_LIB) 186 | $(PRE)$(CC) $< -o $@ $(BN256_LIB) $(MCL_LIB) $(LDFLAGS) -lstdc++ 187 | 188 | SAMPLE_EXE=$(addprefix $(EXE_DIR)/,$(addsuffix .exe,$(basename $(SAMPLE_SRC)))) 189 | sample: $(SAMPLE_EXE) $(MCL_LIB) 190 | 191 | TEST_EXE=$(addprefix $(EXE_DIR)/,$(TEST_SRC:.cpp=.exe)) 192 | test: $(TEST_EXE) 193 | @echo test $(TEST_EXE) 194 | @sh -ec 'for i in $(TEST_EXE); do $$i|grep "ctest:name"; done' > result.txt 195 | @grep -v "ng=0, exception=0" result.txt; if [ $$? -eq 1 ]; then echo "all unit tests succeed"; else exit 1; fi 196 | 197 | EXPORTED_TXT=ffi/js/exported-mcl.txt 198 | EXPORTED_JS=docs/demo/exported-mcl.js 199 | $(EXPORTED_TXT): ./include/mcl/bn.h 200 | python ffi/js/export-functions.py $< > $@ 201 | 202 | $(EXPORTED_JS): ./include/mcl/bn.h 203 | python ffi/js/export-functions.py -js mcl $< > $@ 204 | 205 | EXPORTED_MCL=$(shell cat $(EXPORTED_TXT)) 206 | 207 | docs/demo/mclbn.js: src/fp.cpp src/bn_c256.cpp $(EXPORTED_TXT) $(EXPORTED_JS) 208 | emcc -o $@ src/fp.cpp src/bn_c256.cpp -I./include -I../cybozulib/include -s WASM=1 -s "MODULARIZE=1" -s "EXPORTED_FUNCTIONS=[$(EXPORTED_MCL)]" -O3 -DNDEBUG -DMCLBN_FP_UNIT_SIZE=4 -DMCL_MAX_BIT_SIZE=256 -s DISABLE_EXCEPTION_CATCHING=0 -s NO_EXIT_RUNTIME=1 209 | 210 | demo: 211 | $(MAKE) docs/demo/mclbn.js 212 | 213 | clean: 214 | $(RM) $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(OBJ_DIR)/*.o $(OBJ_DIR)/*.d $(EXE_DIR)/*.exe $(GEN_EXE) $(ASM_OBJ) $(LIB_OBJ) $(BN256_OBJ) $(BN384_OBJ) $(LLVM_SRC) $(FUNC_LIST) src/*.ll $(EXPORTED_JS) $(EXPORTED_TXT) docs/demo/mclbn.js docs/demo/mclbn.wasm 215 | 216 | ALL_SRC=$(SRC_SRC) $(TEST_SRC) $(SAMPLE_SRC) 217 | DEPEND_FILE=$(addprefix $(OBJ_DIR)/, $(addsuffix .d,$(basename $(ALL_SRC)))) 218 | -include $(DEPEND_FILE) 219 | 220 | PREFIX?=/usr/local 221 | install: lib/libmcl.a lib/libmcl$(SHARE_BASENAME_SUF).$(LIB_SUF) 222 | $(MAKE) -C ../cybozulib install PREFIX=$(PREFIX) 223 | $(MKDIR) $(PREFIX)/include/mcl 224 | cp -a include/mcl/ $(PREFIX)/include/ 225 | $(MKDIR) $(PREFIX)/lib 226 | cp -a lib/libmcl.a lib/libmcl$(SHARE_BASENAME_SUF).$(LIB_SUF) $(PREFIX)/lib/ 227 | 228 | .PHONY: test 229 | 230 | # don't remove these files automatically 231 | .SECONDARY: $(addprefix $(OBJ_DIR)/, $(ALL_SRC:.cpp=.o)) 232 | 233 | -------------------------------------------------------------------------------- /mcl/bin/.emptydir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfinity-side-projects/bn/645379f3aab6386bf5f490104584b4a91344ab56/mcl/bin/.emptydir -------------------------------------------------------------------------------- /mcl/common.mk: -------------------------------------------------------------------------------- 1 | GCC_VER=$(shell $(PRE)$(CC) -dumpversion) 2 | UNAME_S=$(shell uname -s) 3 | ifeq ($(UNAME_S),Linux) 4 | OS=Linux 5 | endif 6 | ifeq ($(UNAME_S),Darwin) 7 | OS=mac 8 | ARCH=x86_64 9 | LIB_SUF=dylib 10 | CFLAGS+=-I/usr/local/opt/openssl/include 11 | LDFLAGS+=-L/usr/local/opt/openssl/lib 12 | else 13 | LIB_SUF=so 14 | endif 15 | ARCH?=$(shell uname -m) 16 | DO_IT=0 17 | ifeq ($(ARCH),x86_64) 18 | DO_IT=1 19 | endif 20 | ifeq ($(ARCH),amd64) 21 | DO_IT=1 22 | endif 23 | ifeq ($(DO_IT),1) 24 | CPU=x86-64 25 | INTEL=1 26 | BIT=64 27 | BIT_OPT=-m64 28 | #LOW_ASM_SRC=src/asm/low_x86-64.asm 29 | #ASM=nasm -felf64 30 | endif 31 | ifeq ($(ARCH),x86) 32 | CPU=x86 33 | INTEL=1 34 | BIT=32 35 | BIT_OPT=-m32 36 | #LOW_ASM_SRC=src/asm/low_x86.asm 37 | endif 38 | ifeq ($(ARCH),armv7l) 39 | CPU=arm 40 | BIT=32 41 | #LOW_ASM_SRC=src/asm/low_arm.s 42 | endif 43 | ifeq ($(ARCH),aarch64) 44 | CPU=aarch64 45 | BIT=64 46 | endif 47 | ifneq ($(UNAME_S),Darwin) 48 | LDFLAGS+=-lrt 49 | endif 50 | 51 | CP=cp -f 52 | AR=ar r 53 | MKDIR=mkdir -p 54 | RM=rm -rf 55 | 56 | ifeq ($(DEBUG),1) 57 | ifeq ($(INTEL),1) 58 | CFLAGS+=-fsanitize=address 59 | LDFLAGS+=-fsanitize=address 60 | endif 61 | else 62 | CFLAGS_OPT+=-fomit-frame-pointer -DNDEBUG 63 | ifeq ($(CXX),clang++) 64 | CFLAGS_OPT+=-O3 65 | else 66 | ifeq ($(shell expr $(GCC_VER) \> 4.6.0),1) 67 | CFLAGS_OPT+=-Ofast 68 | else 69 | CFLAGS_OPT+=-O3 70 | endif 71 | endif 72 | ifeq ($(MARCH),) 73 | ifeq ($(INTEL),1) 74 | CFLAGS_OPT+=-march=native 75 | endif 76 | else 77 | CFLAGS_OPT+=$(MARCH) 78 | endif 79 | endif 80 | CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith 81 | CFLAGS+=-g3 82 | INC_OPT=-I include -I test -I ../xbyak -I ../cybozulib/include 83 | CFLAGS+=$(CFLAGS_WARN) $(BIT_OPT) $(INC_OPT) $(CFLAGS_USER) 84 | DEBUG=0 85 | CFLAGS_OPT_USER?=$(CFLAGS_OPT) 86 | ifeq ($(DEBUG),0) 87 | CFLAGS+=$(CFLAGS_OPT_USER) 88 | endif 89 | MCL_USE_GMP?=1 90 | MCL_USE_OPENSSL?=1 91 | ifeq ($(MCL_USE_GMP),0) 92 | CFLAGS+=-DMCL_USE_VINT 93 | endif 94 | ifneq ($(MCL_SIZEOF_UNIT),) 95 | CFLAGS+=-DMCL_SIZEOF_UNIT=$(MCL_SIZEOF_UNIT) 96 | endif 97 | ifeq ($(MCL_USE_OPENSSL),0) 98 | CFLAGS+=-DMCL_DONT_USE_OPENSSL 99 | endif 100 | ifeq ($(MCL_USE_GMP),1) 101 | GMP_LIB=-lgmp -lgmpxx 102 | endif 103 | ifeq ($(MCL_USE_OPENSSL),1) 104 | OPENSSL_LIB=-lcrypto 105 | endif 106 | LDFLAGS+=$(GMP_LIB) $(OPENSSL_LIB) $(BIT_OPT) $(LDFLAGS_USER) 107 | 108 | CFLAGS+=-fPIC 109 | 110 | -------------------------------------------------------------------------------- /mcl/include/mcl/bn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief C interface of 256/384-bit optimal ate pairing over BN curves 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #ifndef MCLBN_FP_UNIT_SIZE 10 | #error "define MCLBN_FP_UNIT_SIZE 4(or 6)" 11 | #endif 12 | 13 | #include // for uint64_t, uint8_t 14 | #include // for size_t 15 | 16 | #ifdef _MSC_VER 17 | #ifdef MCLBN_DLL_EXPORT 18 | #define MCLBN_DLL_API __declspec(dllexport) 19 | #else 20 | #define MCLBN_DLL_API __declspec(dllimport) 21 | #ifndef MCL_NO_AUTOLINK 22 | #if MCLBN_FP_UNIT_SIZE == 4 23 | #pragma comment(lib, "mclbn256.lib") 24 | #else 25 | #pragma comment(lib, "mclbn384.lib") 26 | #endif 27 | #endif 28 | #endif 29 | #else 30 | #define MCLBN_DLL_API 31 | #endif 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | #ifdef MCLBN_NOT_DEFINE_STRUCT 38 | 39 | typedef struct mclBnFr mclBnFr; 40 | typedef struct mclBnG1 mclBnG1; 41 | typedef struct mclBnG2 mclBnG2; 42 | typedef struct mclBnGT mclBnGT; 43 | 44 | #else 45 | 46 | typedef struct { 47 | uint64_t d[MCLBN_FP_UNIT_SIZE]; 48 | } mclBnFr; 49 | 50 | typedef struct { 51 | uint64_t d[MCLBN_FP_UNIT_SIZE * 3]; 52 | } mclBnG1; 53 | 54 | typedef struct { 55 | uint64_t d[MCLBN_FP_UNIT_SIZE * 2 * 3]; 56 | } mclBnG2; 57 | 58 | typedef struct { 59 | uint64_t d[MCLBN_FP_UNIT_SIZE * 12]; 60 | } mclBnGT; 61 | 62 | #endif 63 | 64 | /* 65 | set errlog file name 66 | use stderr if name == "stderr" 67 | close if name == "" 68 | return 0 if success 69 | @note not threadsafe 70 | */ 71 | MCLBN_DLL_API int mclBn_setErrFile(const char *name); 72 | 73 | enum { 74 | mclBn_CurveFp254BNb = 0, 75 | mclBn_CurveFp382_1 = 1, 76 | mclBn_CurveFp382_2 = 2, 77 | mclBn_CurveFp462 = 3 78 | }; 79 | 80 | /* 81 | init library 82 | @param curve [in] type of bn curve 83 | @param maxUnitSize [in] 4 or 6 84 | curve = MCLBN_CurveFp254BNb is allowed if maxUnitSize = 4 85 | curve = MCLBN_CurveFp254BNb/MCLBN_CurveFp382_1/MCLBN_CurveFp382_2 are allowed if maxUnitSize = 6 86 | This parameter is used to detect a library compiled with different MCLBN_FP_UNIT_SIZE for safety. 87 | @note not threadsafe 88 | @note MCLBN_init is used in libeay32 89 | */ 90 | MCLBN_DLL_API int mclBn_init(int curve, int maxUnitSize); 91 | 92 | 93 | /* 94 | pairing : G1 x G2 -> GT 95 | #G1 = #G2 = r 96 | G1 is a curve defined on Fp 97 | 98 | serialized size of elements 99 | |Fr| = |G1| = 32 bytes (if CurveFp254BNb), 48 bytes (if CurevFp382_{1,2}) 100 | |G2| = |G1| * 2 101 | |GT| = |G1| * 12 102 | */ 103 | /* 104 | return the num of Unit(=uint64_t) to store Fr 105 | 4 if curve is mclBn_CurveFp254BNb 106 | 6 if curve is mclBn_CurveFp382_{1,2} 107 | */ 108 | MCLBN_DLL_API int mclBn_getOpUnitSize(); 109 | 110 | /* 111 | return decimal string of the order of the curve(=the characteristic of Fr) 112 | return str(buf) if success 113 | */ 114 | MCLBN_DLL_API size_t mclBn_getCurveOrder(char *buf, size_t maxBufSize); 115 | 116 | /* 117 | return decimal string of the characteristic of Fp 118 | return str(buf) if success 119 | */ 120 | MCLBN_DLL_API size_t mclBn_getFieldOrder(char *buf, size_t maxBufSize); 121 | 122 | //////////////////////////////////////////////// 123 | // set zero 124 | MCLBN_DLL_API void mclBnFr_clear(mclBnFr *x); 125 | 126 | // set x to y 127 | MCLBN_DLL_API void mclBnFr_setInt(mclBnFr *y, int64_t x); 128 | 129 | /* 130 | ioMode 131 | 10 : decimal number 132 | 16 : hexadecimal number 133 | */ 134 | // return 0 if success 135 | MCLBN_DLL_API int mclBnFr_setStr(mclBnFr *x, const char *buf, size_t bufSize, int ioMode); 136 | // return error if buf >= r 137 | MCLBN_DLL_API int mclBnFr_deserialize(mclBnFr *x, const void *buf, size_t bufSize); 138 | // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r 139 | MCLBN_DLL_API int mclBnFr_setLittleEndian(mclBnFr *x, const void *buf, size_t bufSize); 140 | 141 | // return 1 if true and 0 otherwise 142 | MCLBN_DLL_API int mclBnFr_isValid(const mclBnFr *x); 143 | MCLBN_DLL_API int mclBnFr_isEqual(const mclBnFr *x, const mclBnFr *y); 144 | MCLBN_DLL_API int mclBnFr_isZero(const mclBnFr *x); 145 | MCLBN_DLL_API int mclBnFr_isOne(const mclBnFr *x); 146 | 147 | // return 0 if success 148 | MCLBN_DLL_API int mclBnFr_setByCSPRNG(mclBnFr *x); 149 | 150 | // hash(s) and set x 151 | // return 0 if success 152 | MCLBN_DLL_API int mclBnFr_setHashOf(mclBnFr *x, const void *buf, size_t bufSize); 153 | 154 | // return strlen(buf) if sucess else 0 155 | MCLBN_DLL_API size_t mclBnFr_getStr(char *buf, size_t maxBufSize, const mclBnFr *x, int ioMode); 156 | // return written byte if sucess else 0 157 | MCLBN_DLL_API size_t mclBnFr_serialize(void *buf, size_t maxBufSize, const mclBnFr *x); 158 | 159 | MCLBN_DLL_API void mclBnFr_neg(mclBnFr *y, const mclBnFr *x); 160 | MCLBN_DLL_API void mclBnFr_inv(mclBnFr *y, const mclBnFr *x); 161 | MCLBN_DLL_API void mclBnFr_add(mclBnFr *z, const mclBnFr *x, const mclBnFr *y); 162 | MCLBN_DLL_API void mclBnFr_sub(mclBnFr *z, const mclBnFr *x, const mclBnFr *y); 163 | MCLBN_DLL_API void mclBnFr_mul(mclBnFr *z, const mclBnFr *x, const mclBnFr *y); 164 | MCLBN_DLL_API void mclBnFr_div(mclBnFr *z, const mclBnFr *x, const mclBnFr *y); 165 | 166 | //////////////////////////////////////////////// 167 | // set zero 168 | MCLBN_DLL_API void mclBnG1_clear(mclBnG1 *x); 169 | 170 | // return 0 if success 171 | MCLBN_DLL_API int mclBnG1_setStr(mclBnG1 *x, const char *buf, size_t bufSize, int ioMode); 172 | MCLBN_DLL_API int mclBnG1_deserialize(mclBnG1 *x, const void *buf, size_t bufSize); 173 | 174 | // return 1 if true and 0 otherwise 175 | MCLBN_DLL_API int mclBnG1_isValid(const mclBnG1 *x); 176 | MCLBN_DLL_API int mclBnG1_isEqual(const mclBnG1 *x, const mclBnG1 *y); 177 | MCLBN_DLL_API int mclBnG1_isZero(const mclBnG1 *x); 178 | 179 | MCLBN_DLL_API int mclBnG1_hashAndMapTo(mclBnG1 *x, const void *buf, size_t bufSize); 180 | 181 | // return 0 if success 182 | MCLBN_DLL_API size_t mclBnG1_getStr(char *buf, size_t maxBufSize, const mclBnG1 *x, int ioMode); 183 | // return written size if sucess else 0 184 | MCLBN_DLL_API size_t mclBnG1_serialize(void *buf, size_t maxBufSize, const mclBnG1 *x); 185 | 186 | MCLBN_DLL_API void mclBnG1_neg(mclBnG1 *y, const mclBnG1 *x); 187 | MCLBN_DLL_API void mclBnG1_dbl(mclBnG1 *y, const mclBnG1 *x); 188 | MCLBN_DLL_API void mclBnG1_add(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y); 189 | MCLBN_DLL_API void mclBnG1_sub(mclBnG1 *z, const mclBnG1 *x, const mclBnG1 *y); 190 | MCLBN_DLL_API void mclBnG1_mul(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y); 191 | 192 | /* 193 | constant time mul 194 | */ 195 | MCLBN_DLL_API void mclBnG1_mulCT(mclBnG1 *z, const mclBnG1 *x, const mclBnFr *y); 196 | 197 | //////////////////////////////////////////////// 198 | // set zero 199 | MCLBN_DLL_API void mclBnG2_clear(mclBnG2 *x); 200 | 201 | // return 0 if success 202 | MCLBN_DLL_API int mclBnG2_setStr(mclBnG2 *x, const char *buf, size_t bufSize, int ioMode); 203 | MCLBN_DLL_API int mclBnG2_deserialize(mclBnG2 *x, const void *buf, size_t bufSize); 204 | 205 | // return 1 if true and 0 otherwise 206 | MCLBN_DLL_API int mclBnG2_isValid(const mclBnG2 *x); 207 | MCLBN_DLL_API int mclBnG2_isEqual(const mclBnG2 *x, const mclBnG2 *y); 208 | MCLBN_DLL_API int mclBnG2_isZero(const mclBnG2 *x); 209 | 210 | MCLBN_DLL_API int mclBnG2_hashAndMapTo(mclBnG2 *x, const void *buf, size_t bufSize); 211 | 212 | // return 0 if success 213 | MCLBN_DLL_API size_t mclBnG2_getStr(char *buf, size_t maxBufSize, const mclBnG2 *x, int ioMode); 214 | // return written size if sucess else 0 215 | MCLBN_DLL_API size_t mclBnG2_serialize(void *buf, size_t maxBufSize, const mclBnG2 *x); 216 | 217 | MCLBN_DLL_API void mclBnG2_neg(mclBnG2 *y, const mclBnG2 *x); 218 | MCLBN_DLL_API void mclBnG2_dbl(mclBnG2 *y, const mclBnG2 *x); 219 | MCLBN_DLL_API void mclBnG2_add(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y); 220 | MCLBN_DLL_API void mclBnG2_sub(mclBnG2 *z, const mclBnG2 *x, const mclBnG2 *y); 221 | MCLBN_DLL_API void mclBnG2_mul(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y); 222 | /* 223 | constant time mul 224 | */ 225 | MCLBN_DLL_API void mclBnG2_mulCT(mclBnG2 *z, const mclBnG2 *x, const mclBnFr *y); 226 | 227 | //////////////////////////////////////////////// 228 | // set zero 229 | MCLBN_DLL_API void mclBnGT_clear(mclBnGT *x); 230 | // set x to y 231 | MCLBN_DLL_API void mclBnGT_setInt(mclBnGT *y, int64_t x); 232 | 233 | // return 0 if success 234 | MCLBN_DLL_API int mclBnGT_setStr(mclBnGT *x, const char *buf, size_t bufSize, int ioMode); 235 | MCLBN_DLL_API int mclBnGT_deserialize(mclBnGT *x, const void *buf, size_t bufSize); 236 | 237 | // return 1 if true and 0 otherwise 238 | MCLBN_DLL_API int mclBnGT_isEqual(const mclBnGT *x, const mclBnGT *y); 239 | MCLBN_DLL_API int mclBnGT_isZero(const mclBnGT *x); 240 | MCLBN_DLL_API int mclBnGT_isOne(const mclBnGT *x); 241 | 242 | // return 0 if success 243 | MCLBN_DLL_API size_t mclBnGT_getStr(char *buf, size_t maxBufSize, const mclBnGT *x, int ioMode); 244 | // return written size if sucess else 0 245 | MCLBN_DLL_API size_t mclBnGT_serialize(void *buf, size_t maxBufSize, const mclBnGT *x); 246 | 247 | MCLBN_DLL_API void mclBnGT_neg(mclBnGT *y, const mclBnGT *x); 248 | MCLBN_DLL_API void mclBnGT_inv(mclBnGT *y, const mclBnGT *x); 249 | MCLBN_DLL_API void mclBnGT_add(mclBnGT *z, const mclBnGT *x, const mclBnGT *y); 250 | MCLBN_DLL_API void mclBnGT_sub(mclBnGT *z, const mclBnGT *x, const mclBnGT *y); 251 | MCLBN_DLL_API void mclBnGT_mul(mclBnGT *z, const mclBnGT *x, const mclBnGT *y); 252 | MCLBN_DLL_API void mclBnGT_div(mclBnGT *z, const mclBnGT *x, const mclBnGT *y); 253 | 254 | /* 255 | pow for all elements of Fp12 256 | */ 257 | MCLBN_DLL_API void mclBnGT_powGeneric(mclBnGT *z, const mclBnGT *x, const mclBnFr *y); 258 | /* 259 | pow for only {x|x^r = 1} in Fp12 by GLV method 260 | the value generated by pairing satisfies the condition 261 | */ 262 | MCLBN_DLL_API void mclBnGT_pow(mclBnGT *z, const mclBnGT *x, const mclBnFr *y); 263 | 264 | MCLBN_DLL_API void mclBn_pairing(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y); 265 | MCLBN_DLL_API void mclBn_finalExp(mclBnGT *y, const mclBnGT *x); 266 | MCLBN_DLL_API void mclBn_millerLoop(mclBnGT *z, const mclBnG1 *x, const mclBnG2 *y); 267 | 268 | // return precomputedQcoeffSize * sizeof(Fp6) / sizeof(uint64_t) 269 | MCLBN_DLL_API int mclBn_getUint64NumToPrecompute(void); 270 | 271 | // allocate Qbuf[MCLBN_getUint64NumToPrecompute()] before calling this 272 | MCLBN_DLL_API void mclBn_precomputeG2(uint64_t *Qbuf, const mclBnG2 *Q); 273 | 274 | MCLBN_DLL_API void mclBn_precomputedMillerLoop(mclBnGT *f, const mclBnG1 *P, const uint64_t *Qbuf); 275 | MCLBN_DLL_API void mclBn_precomputedMillerLoop2(mclBnGT *f, const mclBnG1 *P1, const uint64_t *Q1buf, const mclBnG1 *P2, const uint64_t *Q2buf); 276 | 277 | /* 278 | Lagrange interpolation 279 | recover out = y(0) by { (xVec[i], yVec[i]) } 280 | return 0 if success else -1 281 | @note k >= 2, xVec[i] != 0, xVec[i] != xVec[j] for i != j 282 | */ 283 | MCLBN_DLL_API int mclBn_FrLagrangeInterpolation(mclBnFr *out, const mclBnFr *xVec, const mclBnFr *yVec, size_t k); 284 | MCLBN_DLL_API int mclBn_G1LagrangeInterpolation(mclBnG1 *out, const mclBnFr *xVec, const mclBnG1 *yVec, size_t k); 285 | MCLBN_DLL_API int mclBn_G2LagrangeInterpolation(mclBnG2 *out, const mclBnFr *xVec, const mclBnG2 *yVec, size_t k); 286 | 287 | /* 288 | evaluate polynomial 289 | out = f(x) = c[0] + c[1] * x + c[2] * x^2 + ... + c[cSize - 1] * x^(cSize - 1) 290 | @note cSize >= 2 291 | */ 292 | MCLBN_DLL_API int mclBn_FrEvaluatePolynomial(mclBnFr *out, const mclBnFr *cVec, size_t cSize, const mclBnFr *x); 293 | MCLBN_DLL_API int mclBn_G1EvaluatePolynomial(mclBnG1 *out, const mclBnG1 *cVec, size_t cSize, const mclBnFr *x); 294 | MCLBN_DLL_API int mclBn_G2EvaluatePolynomial(mclBnG2 *out, const mclBnG2 *cVec, size_t cSize, const mclBnFr *x); 295 | 296 | 297 | #ifdef __cplusplus 298 | } 299 | #endif 300 | -------------------------------------------------------------------------------- /mcl/include/mcl/bn256.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief preset class for 256-bit optimal ate pairing over BN curves 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | 11 | namespace mcl { namespace bn256 { 12 | 13 | namespace local { 14 | struct FpTag; 15 | struct FrTag; 16 | } 17 | 18 | typedef mcl::FpT Fp; 19 | typedef mcl::bn::BNT BN; 20 | typedef BN::Fp2 Fp2; 21 | typedef BN::Fp6 Fp6; 22 | typedef BN::Fp12 Fp12; 23 | typedef BN::G1 G1; 24 | typedef BN::G2 G2; 25 | typedef BN::Fp12 GT; 26 | 27 | /* the order of G1 is r */ 28 | typedef mcl::FpT Fr; 29 | 30 | static inline void initPairing(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp254BNb, fp::Mode mode = fp::FP_AUTO) 31 | { 32 | BN::init(cp, mode); 33 | G1::setCompressedExpression(); 34 | G2::setCompressedExpression(); 35 | Fr::init(BN::param.r); 36 | } 37 | 38 | static inline void bn256init(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp254BNb, fp::Mode mode = fp::FP_AUTO) 39 | { 40 | initPairing(cp, mode); 41 | } 42 | 43 | } } // mcl::bn256 44 | 45 | -------------------------------------------------------------------------------- /mcl/include/mcl/bn384.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief preset class for 384-bit optimal ate pairing over BN curves 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | 11 | namespace mcl { namespace bn384 { 12 | 13 | namespace local { 14 | struct FpTag; 15 | struct FrTag; 16 | } 17 | 18 | typedef mcl::FpT Fp; 19 | typedef mcl::bn::BNT BN; 20 | typedef BN::Fp2 Fp2; 21 | typedef BN::Fp6 Fp6; 22 | typedef BN::Fp12 Fp12; 23 | typedef BN::G1 G1; 24 | typedef BN::G2 G2; 25 | typedef BN::Fp12 GT; 26 | 27 | /* the order of G1 is r */ 28 | typedef mcl::FpT Fr; 29 | 30 | static inline void initPairing(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp382_2, fp::Mode mode = fp::FP_AUTO) 31 | { 32 | BN::init(cp, mode); 33 | G1::setCompressedExpression(); 34 | G2::setCompressedExpression(); 35 | Fr::init(BN::param.r); 36 | } 37 | 38 | static inline void bn384init(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp382_2, fp::Mode mode = fp::FP_AUTO) 39 | { 40 | initPairing(cp, mode); 41 | } 42 | 43 | } } // mcl::bn384 44 | 45 | -------------------------------------------------------------------------------- /mcl/include/mcl/bn512.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief preset class for 512-bit optimal ate pairing over BN curves 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | 11 | namespace mcl { namespace bn512 { 12 | 13 | namespace local { 14 | struct FpTag; 15 | struct FrTag; 16 | } 17 | 18 | typedef mcl::FpT Fp; 19 | typedef mcl::bn::BNT BN; 20 | typedef BN::Fp2 Fp2; 21 | typedef BN::Fp6 Fp6; 22 | typedef BN::Fp12 Fp12; 23 | typedef BN::G1 G1; 24 | typedef BN::G2 G2; 25 | typedef BN::Fp12 GT; 26 | 27 | /* the order of G1 is r */ 28 | typedef mcl::FpT Fr; 29 | 30 | static inline void initPairing(const mcl::bn::CurveParam& cp = mcl::bn::CurveFp254BNb, fp::Mode mode = fp::FP_AUTO) 31 | { 32 | BN::init(cp, mode); 33 | G1::setCompressedExpression(); 34 | G2::setCompressedExpression(); 35 | Fr::init(BN::param.r); 36 | } 37 | 38 | } } // mcl::bn512 39 | 40 | -------------------------------------------------------------------------------- /mcl/include/mcl/ecparam.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief Elliptic curve parameter 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | 11 | namespace mcl { namespace ecparam { 12 | 13 | const struct mcl::EcParam secp160k1 = { 14 | "secp160k1", 15 | "0xfffffffffffffffffffffffffffffffeffffac73", 16 | "0", 17 | "7", 18 | "0x3b4c382ce37aa192a4019e763036f4f5dd4d7ebb", 19 | "0x938cf935318fdced6bc28286531733c3f03c4fee", 20 | "0x100000000000000000001b8fa16dfab9aca16b6b3", 21 | 160 22 | }; 23 | // p=2^160 + 7 24 | const struct mcl::EcParam p160_1 = { 25 | "p160_1", 26 | "0x10000000000000000000000000000000000000007", 27 | "10", 28 | "1343632762150092499701637438970764818528075565078", 29 | "1", 30 | "1236612389951462151661156731535316138439983579284", 31 | "1461501637330902918203683518218126812711137002561", 32 | 161 33 | }; 34 | const struct mcl::EcParam secp192k1 = { 35 | "secp192k1", 36 | "0xfffffffffffffffffffffffffffffffffffffffeffffee37", 37 | "0", 38 | "3", 39 | "0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d", 40 | "0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d", 41 | "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d", 42 | 192 43 | }; 44 | const struct mcl::EcParam secp224k1 = { 45 | "secp224k1", 46 | "0xfffffffffffffffffffffffffffffffffffffffffffffffeffffe56d", 47 | "0", 48 | "5", 49 | "0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c", 50 | "0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5", 51 | "0x10000000000000000000000000001dce8d2ec6184caf0a971769fb1f7", 52 | 224 53 | }; 54 | const struct mcl::EcParam secp256k1 = { 55 | "secp256k1", 56 | "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 57 | "0", 58 | "7", 59 | "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 60 | "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", 61 | "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 62 | 256 63 | }; 64 | const struct mcl::EcParam secp384r1 = { 65 | "secp384r1", 66 | "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff", 67 | "-3", 68 | "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 69 | "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 70 | "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 71 | "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973", 72 | 384 73 | }; 74 | const struct mcl::EcParam secp521r1 = { 75 | "secp521r1", 76 | "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 77 | "-3", 78 | "0x51953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 79 | "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 80 | "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 81 | "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", 82 | 521 83 | }; 84 | const struct mcl::EcParam NIST_P192 = { 85 | "NIST_P192", 86 | "0xfffffffffffffffffffffffffffffffeffffffffffffffff", 87 | "-3", 88 | "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 89 | "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 90 | "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811", 91 | "0xffffffffffffffffffffffff99def836146bc9b1b4d22831", 92 | 192 93 | }; 94 | const struct mcl::EcParam NIST_P224 = { 95 | "NIST_P224", 96 | "0xffffffffffffffffffffffffffffffff000000000000000000000001", 97 | "-3", 98 | "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 99 | "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 100 | "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 101 | "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d", 102 | 224 103 | }; 104 | const struct mcl::EcParam NIST_P256 = { 105 | "NIST_P256", 106 | "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 107 | "-3", 108 | "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 109 | "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 110 | "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 111 | "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 112 | 256 113 | }; 114 | // same secp384r1 115 | const struct mcl::EcParam NIST_P384 = { 116 | "NIST_P384", 117 | "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff", 118 | "-3", 119 | "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 120 | "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 121 | "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 122 | "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973", 123 | 384 124 | }; 125 | // same secp521r1 126 | const struct mcl::EcParam NIST_P521 = { 127 | "NIST_P521", 128 | "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 129 | "-3", 130 | "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 131 | "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 132 | "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 133 | "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", 134 | 521 135 | }; 136 | 137 | } // mcl::ecparam 138 | 139 | static inline const mcl::EcParam* getEcParam(const std::string& name) 140 | { 141 | static const mcl::EcParam *tbl[] = { 142 | &ecparam::p160_1, 143 | &ecparam::secp160k1, 144 | &ecparam::secp192k1, 145 | &ecparam::secp224k1, 146 | &ecparam::secp256k1, 147 | &ecparam::secp384r1, 148 | &ecparam::secp521r1, 149 | 150 | &ecparam::NIST_P192, 151 | &ecparam::NIST_P224, 152 | &ecparam::NIST_P256, 153 | &ecparam::NIST_P384, 154 | &ecparam::NIST_P521, 155 | }; 156 | for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { 157 | if (name == tbl[i]->name) return tbl[i]; 158 | } 159 | throw cybozu::Exception("mcl::getEcParam:not support name") << name; 160 | } 161 | 162 | } // mcl 163 | -------------------------------------------------------------------------------- /mcl/include/mcl/fp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief finite field class 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | #include 11 | #include 12 | #ifdef _MSC_VER 13 | #pragma warning(push) 14 | #pragma warning(disable : 4127) 15 | #pragma warning(disable : 4458) 16 | #ifndef NOMINMAX 17 | #define NOMINMAX 18 | #endif 19 | #ifndef MCL_NO_AUTOLINK 20 | #ifdef NDEBUG 21 | #pragma comment(lib, "mcl.lib") 22 | #else 23 | #pragma comment(lib, "mcl.lib") 24 | #endif 25 | #endif 26 | #endif 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace mcl { 33 | 34 | struct FpTag; 35 | struct ZnTag; 36 | 37 | namespace fp { 38 | 39 | // copy src to dst as little endian 40 | void copyUnitToByteAsLE(uint8_t *dst, const Unit *src, size_t byteSize); 41 | // copy src to dst as little endian 42 | void copyByteToUnitAsLE(Unit *dst, const uint8_t *src, size_t byteSize); 43 | void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask); 44 | 45 | uint64_t getUint64(bool *pb, const fp::Block& b); 46 | int64_t getInt64(bool *pb, fp::Block& b, const fp::Op& op); 47 | 48 | const char *ModeToStr(Mode mode); 49 | 50 | Mode StrToMode(const std::string& s); 51 | 52 | void dumpUnit(Unit x); 53 | void UnitToHex(char *buf, size_t maxBufSize, Unit x); 54 | std::string hexStrToLittleEndian(const char *buf, size_t bufSize); 55 | std::string littleEndianToHexStr(const void *buf, size_t bufSize); 56 | 57 | bool isEnableJIT(); // 1st call is not threadsafe 58 | 59 | // hash msg 60 | std::string hash(size_t bitSize, const void *msg, size_t msgSize); 61 | 62 | } // mcl::fp 63 | 64 | template 65 | class FpT : public fp::Operator > { 66 | typedef fp::Unit Unit; 67 | typedef fp::Operator > Operator; 68 | public: 69 | static const size_t maxSize = (maxBitSize + fp::UnitBitSize - 1) / fp::UnitBitSize; 70 | private: 71 | template friend class FpT; 72 | Unit v_[maxSize]; 73 | static fp::Op op_; 74 | static FpT inv2_; 75 | static int ioMode_; 76 | template friend class FpDblT; 77 | template friend class Fp2T; 78 | template friend struct Fp6T; 79 | public: 80 | typedef FpT BaseFp; 81 | // return pointer to array v_[] 82 | const Unit *getUnit() const { return v_; } 83 | FpT* getFp0() { return this; } 84 | const FpT* getFp0() const { return this; } 85 | static inline size_t getUnitSize() { return op_.N; } 86 | static inline size_t getBitSize() { return op_.bitSize; } 87 | static inline size_t getByteSize() { return (op_.bitSize + 7) / 8; } 88 | static inline const fp::Op& getOp() { return op_; } 89 | void dump() const 90 | { 91 | const size_t N = op_.N; 92 | for (size_t i = 0; i < N; i++) { 93 | fp::dumpUnit(v_[N - 1 - i]); 94 | } 95 | printf("\n"); 96 | } 97 | static inline void init(const mpz_class& m, fp::Mode mode = fp::FP_AUTO) 98 | { 99 | init(gmp::getStr(m), mode); 100 | } 101 | static inline void init(const std::string& mstr, fp::Mode mode = fp::FP_AUTO) 102 | { 103 | assert(maxBitSize <= MCL_MAX_BIT_SIZE); 104 | op_.init(mstr, maxBitSize, mode); 105 | { // set oneRep 106 | FpT& one = *reinterpret_cast(op_.oneRep); 107 | one.clear(); 108 | one.v_[0] = 1; 109 | one.toMont(); 110 | } 111 | { // set half 112 | mpz_class half = (op_.mp + 1) / 2; 113 | gmp::getArray(op_.half, op_.N, half); 114 | } 115 | inv(inv2_, 2); 116 | } 117 | static inline void getModulo(std::string& pstr) 118 | { 119 | gmp::getStr(pstr, op_.mp); 120 | } 121 | static inline bool isFullBit() { return op_.isFullBit; } 122 | /* 123 | binary patter of p 124 | @note the value of p is zero 125 | */ 126 | static inline const FpT& getP() 127 | { 128 | return *reinterpret_cast(op_.p); 129 | } 130 | bool isOdd() const 131 | { 132 | fp::Block b; 133 | getBlock(b); 134 | return (b.p[0] & 1) == 1; 135 | } 136 | static inline bool squareRoot(FpT& y, const FpT& x) 137 | { 138 | if (isMont()) return op_.sq.get(y, x); 139 | mpz_class mx, my; 140 | x.getMpz(mx); 141 | bool b = op_.sq.get(my, mx); 142 | if (!b) return false; 143 | y.setMpz(my); 144 | return true; 145 | } 146 | FpT() {} 147 | FpT(const FpT& x) 148 | { 149 | op_.fp_copy(v_, x.v_); 150 | } 151 | FpT& operator=(const FpT& x) 152 | { 153 | op_.fp_copy(v_, x.v_); 154 | return *this; 155 | } 156 | void clear() 157 | { 158 | op_.fp_clear(v_); 159 | } 160 | FpT(int64_t x) { operator=(x); } 161 | explicit FpT(const std::string& str, int base = 0) 162 | { 163 | setStr(str, base); 164 | } 165 | FpT& operator=(int64_t x) 166 | { 167 | if (x == 1) { 168 | op_.fp_copy(v_, op_.oneRep); 169 | } else { 170 | clear(); 171 | if (x) { 172 | int64_t y = x < 0 ? -x : x; 173 | if (sizeof(Unit) == 8) { 174 | v_[0] = y; 175 | } else { 176 | v_[0] = (uint32_t)y; 177 | v_[1] = (uint32_t)(y >> 32); 178 | } 179 | if (x < 0) neg(*this, *this); 180 | toMont(); 181 | } 182 | } 183 | return *this; 184 | } 185 | static inline bool isMont() { return op_.isMont; } 186 | /* 187 | convert normal value to Montgomery value 188 | do nothing is !isMont() 189 | */ 190 | void toMont() 191 | { 192 | if (isMont()) op_.toMont(v_, v_); 193 | } 194 | /* 195 | convert Montgomery value to normal value 196 | do nothing is !isMont() 197 | */ 198 | void fromMont() 199 | { 200 | if (isMont()) op_.fromMont(v_, v_); 201 | } 202 | std::istream& readStream(std::istream& is, int ioMode) 203 | { 204 | bool isMinus; 205 | fp::streamToArray(&isMinus, v_, FpT::getByteSize(), is, ioMode); 206 | if (fp::isGreaterOrEqualArray(v_, op_.p, op_.N)) throw cybozu::Exception("FpT:readStream:large value"); 207 | if (!(ioMode & IoArrayRaw)) { 208 | if (isMinus) { 209 | neg(*this, *this); 210 | } 211 | toMont(); 212 | } 213 | return is; 214 | } 215 | void setStr(const std::string& str, int ioMode = 0) 216 | { 217 | std::istringstream is(str); 218 | readStream(is, ioMode); 219 | } 220 | /* 221 | throw exception if x >= p 222 | */ 223 | template 224 | void setArray(const S *x, size_t n) 225 | { 226 | fp::copyAndMask(v_, x, sizeof(S) * n, op_, false); 227 | toMont(); 228 | } 229 | /* 230 | mask inBuf with (1 << (bitLen - 1)) - 1 if x >= p 231 | */ 232 | template 233 | void setArrayMask(const S *inBuf, size_t n) 234 | { 235 | fp::copyAndMask(v_, inBuf, sizeof(S) * n, op_, true); 236 | toMont(); 237 | } 238 | void getBlock(fp::Block& b) const 239 | { 240 | b.n = op_.N; 241 | if (isMont()) { 242 | op_.fromMont(b.v_, v_); 243 | b.p = &b.v_[0]; 244 | } else { 245 | b.p = &v_[0]; 246 | } 247 | } 248 | template 249 | void setRand(RG& rg) 250 | { 251 | fp::getRandVal(v_, rg, op_.p, op_.bitSize); 252 | toMont(); 253 | } 254 | /* 255 | hash msg and mask with (1 << (bitLen - 1)) - 1 256 | */ 257 | void setHashOf(const void *msg, size_t msgSize) 258 | { 259 | std::string digest = mcl::fp::hash(op_.bitSize, msg, msgSize); 260 | setArrayMask(digest.c_str(), digest.size()); 261 | } 262 | void setHashOf(const std::string& msg) 263 | { 264 | setHashOf(msg.data(), msg.size()); 265 | } 266 | #ifdef _MSC_VER 267 | #pragma warning(push) 268 | #pragma warning(disable:4701) 269 | #endif 270 | void getStr(std::string& str, int ioMode = 0) const 271 | { 272 | fp::Block b; 273 | const size_t n = getByteSize(); 274 | const Unit *p = v_; 275 | if (!(ioMode & IoArrayRaw)) { 276 | getBlock(b); 277 | p = b.p; 278 | } 279 | if (ioMode & (IoArray | IoArrayRaw | IoFixedSizeByteSeq)) { 280 | str.resize(n); 281 | fp::copyUnitToByteAsLE(reinterpret_cast(&str[0]), p, str.size()); 282 | return; 283 | } 284 | // use low 8-bit ioMode for Fp 285 | fp::arrayToStr(str, b.p, b.n, ioMode & 255); 286 | } 287 | #ifdef _MSC_VER 288 | #pragma warning(pop) 289 | #endif 290 | std::string getStr(int ioMode = 0) const 291 | { 292 | std::string str; 293 | getStr(str, ioMode); 294 | return str; 295 | } 296 | void getMpz(mpz_class& x) const 297 | { 298 | fp::Block b; 299 | getBlock(b); 300 | gmp::setArray(x, b.p, b.n); 301 | } 302 | mpz_class getMpz() const 303 | { 304 | mpz_class x; 305 | getMpz(x); 306 | return x; 307 | } 308 | void setMpz(const mpz_class& x) 309 | { 310 | if (x < 0) throw cybozu::Exception("Fp:setMpz:negative is not supported") << x; 311 | setArray(gmp::getUnit(x), gmp::getUnitSize(x)); 312 | } 313 | static inline void add(FpT& z, const FpT& x, const FpT& y) { op_.fp_add(z.v_, x.v_, y.v_, op_.p); } 314 | static inline void sub(FpT& z, const FpT& x, const FpT& y) { op_.fp_sub(z.v_, x.v_, y.v_, op_.p); } 315 | static inline void addPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_addPre(z.v_, x.v_, y.v_); } 316 | static inline void subPre(FpT& z, const FpT& x, const FpT& y) { op_.fp_subPre(z.v_, x.v_, y.v_); } 317 | static inline void mul(FpT& z, const FpT& x, const FpT& y) { op_.fp_mul(z.v_, x.v_, y.v_, op_.p); } 318 | static inline void mulUnit(FpT& z, const FpT& x, const Unit y) 319 | { 320 | if (mulSmallUnit(z, x, y)) return; 321 | op_.fp_mulUnit(z.v_, x.v_, y, op_.p); 322 | } 323 | static inline void inv(FpT& y, const FpT& x) { op_.fp_invOp(y.v_, x.v_, op_); } 324 | static inline void neg(FpT& y, const FpT& x) { op_.fp_neg(y.v_, x.v_, op_.p); } 325 | static inline void sqr(FpT& y, const FpT& x) { op_.fp_sqr(y.v_, x.v_, op_.p); } 326 | static inline void divBy2(FpT& y, const FpT& x) 327 | { 328 | #if 0 329 | mul(y, x, inv2_); 330 | #else 331 | bool odd = (x.v_[0] & 1) != 0; 332 | op_.fp_shr1(y.v_, x.v_); 333 | if (odd) { 334 | op_.fp_addPre(y.v_, y.v_, op_.half); 335 | } 336 | #endif 337 | } 338 | static inline void divBy4(FpT& y, const FpT& x) 339 | { 340 | divBy2(y, x); // QQQ : optimize later 341 | divBy2(y, y); 342 | } 343 | bool isZero() const { return op_.fp_isZero(v_); } 344 | bool isOne() const { return fp::isEqualArray(v_, op_.oneRep, op_.N); } 345 | static const inline FpT& one() { return *reinterpret_cast(op_.oneRep); } 346 | /* 347 | half = (p + 1) / 2 348 | return true if half <= x < p 349 | return false if 0 <= x < half 350 | */ 351 | bool isNegative() const 352 | { 353 | fp::Block b; 354 | getBlock(b); 355 | return fp::isGreaterOrEqualArray(b.p, op_.half, op_.N); 356 | } 357 | bool isValid() const 358 | { 359 | return fp::isLessArray(v_, op_.p, op_.N); 360 | } 361 | uint64_t getUint64(bool *pb = 0) const 362 | { 363 | fp::Block b; 364 | getBlock(b); 365 | return fp::getUint64(pb, b); 366 | } 367 | int64_t getInt64(bool *pb = 0) const 368 | { 369 | fp::Block b; 370 | getBlock(b); 371 | return fp::getInt64(pb, b, op_); 372 | } 373 | bool operator==(const FpT& rhs) const { return fp::isEqualArray(v_, rhs.v_, op_.N); } 374 | bool operator!=(const FpT& rhs) const { return !operator==(rhs); } 375 | friend inline std::ostream& operator<<(std::ostream& os, const FpT& self) 376 | { 377 | return os << self.getStr(fp::detectIoMode(getIoMode(), os)); 378 | } 379 | friend inline std::istream& operator>>(std::istream& is, FpT& self) 380 | { 381 | return self.readStream(is, fp::detectIoMode(getIoMode(), is)); 382 | } 383 | /* 384 | @note 385 | this compare functions is slow because of calling mul if isMont is true. 386 | */ 387 | static inline int compare(const FpT& x, const FpT& y) 388 | { 389 | fp::Block xb, yb; 390 | x.getBlock(xb); 391 | y.getBlock(yb); 392 | return fp::compareArray(xb.p, yb.p, op_.N); 393 | } 394 | bool isLess(const FpT& rhs) const 395 | { 396 | fp::Block xb, yb; 397 | getBlock(xb); 398 | rhs.getBlock(yb); 399 | return fp::isLessArray(xb.p, yb.p, op_.N); 400 | } 401 | bool operator<(const FpT& rhs) const { return isLess(rhs); } 402 | bool operator>=(const FpT& rhs) const { return !operator<(rhs); } 403 | bool operator>(const FpT& rhs) const { return rhs < *this; } 404 | bool operator<=(const FpT& rhs) const { return !operator>(rhs); } 405 | /* 406 | @note 407 | return unexpected order if isMont is set. 408 | */ 409 | static inline int compareRaw(const FpT& x, const FpT& y) 410 | { 411 | return fp::compareArray(x.v_, y.v_, op_.N); 412 | } 413 | bool isLessRaw(const FpT& rhs) const 414 | { 415 | return fp::isLessArray(v_, rhs.v_, op_.N); 416 | } 417 | /* 418 | set IoMode for operator<<(), or operator>>() 419 | */ 420 | static inline void setIoMode(int ioMode) 421 | { 422 | if (ioMode_ & ~0xff) throw cybozu::Exception("FpT:setIoMode:bad mode") << ioMode; 423 | ioMode_ = ioMode; 424 | } 425 | static inline int getIoMode() { return ioMode_; } 426 | // backward compatibility 427 | static inline void setModulo(const std::string& mstr, fp::Mode mode = fp::FP_AUTO) 428 | { 429 | init(mstr, mode); 430 | } 431 | static inline size_t getModBitLen() { return getBitSize(); } 432 | }; 433 | 434 | template fp::Op FpT::op_; 435 | template FpT FpT::inv2_; 436 | template int FpT::ioMode_ = IoAuto; 437 | 438 | } // mcl 439 | 440 | #ifdef CYBOZU_USE_BOOST 441 | namespace mcl { 442 | 443 | template 444 | size_t hash_value(const mcl::FpT& x, size_t v = 0) 445 | { 446 | return static_cast(cybozu::hash64(x.getUnit(), x.getUnitSize(), v)); 447 | } 448 | 449 | } 450 | #else 451 | namespace std { CYBOZU_NAMESPACE_TR1_BEGIN 452 | 453 | template 454 | struct hash > { 455 | size_t operator()(const mcl::FpT& x, uint64_t v = 0) const 456 | { 457 | return static_cast(cybozu::hash64(x.getUnit(), x.getUnitSize(), v)); 458 | } 459 | }; 460 | 461 | CYBOZU_NAMESPACE_TR1_END } // std::tr1 462 | #endif 463 | 464 | #ifdef _WIN32 465 | #pragma warning(pop) 466 | #endif 467 | -------------------------------------------------------------------------------- /mcl/include/mcl/lagrange.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief Lagrange Interpolation 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | 11 | namespace mcl { 12 | 13 | /* 14 | recover out = f(0) by { (x, y) | x = S[i], y = f(x) = vec[i] } 15 | @retval 0 if succeed else -1 16 | */ 17 | template 18 | void LagrangeInterpolation(G& out, const F *S, const G *vec, size_t k) 19 | { 20 | /* 21 | delta_{i,S}(0) = prod_{j != i} S[j] / (S[j] - S[i]) = a / b 22 | where a = prod S[j], b = S[i] * prod_{j != i} (S[j] - S[i]) 23 | */ 24 | if (k < 2) throw cybozu::Exception("LagrangeInterpolation:smalll k") << k; 25 | std::vector delta(k); 26 | F a = S[0]; 27 | for (size_t i = 1; i < k; i++) { 28 | a *= S[i]; 29 | } 30 | if (a.isZero()) throw cybozu::Exception("LagrangeInterpolation:S has zero"); 31 | for (size_t i = 0; i < k; i++) { 32 | F b = S[i]; 33 | for (size_t j = 0; j < k; j++) { 34 | if (j != i) { 35 | F v = S[j] - S[i]; 36 | if (v.isZero()) throw cybozu::Exception("LagrangeInterpolation:same S") << i << j; 37 | b *= v; 38 | } 39 | } 40 | delta[i] = a / b; 41 | } 42 | 43 | /* 44 | f(0) = sum_i f(S[i]) delta_{i,S}(0) 45 | */ 46 | G r, t; 47 | r.clear(); 48 | for (size_t i = 0; i < delta.size(); i++) { 49 | G::mul(t, vec[i], delta[i]); 50 | r += t; 51 | } 52 | out = r; 53 | } 54 | 55 | /* 56 | out = f(x) = c[0] + c[1] * x + c[2] * x^2 + ... + c[cSize - 1] * x^(cSize - 1) 57 | @retval 0 if succeed else -1 58 | */ 59 | template 60 | void evaluatePolynomial(G& out, const G *c, size_t cSize, const T& x) 61 | { 62 | if (cSize < 2) throw cybozu::Exception("evaluatePolynomial:small cSize") << cSize; 63 | G y = c[cSize - 1]; 64 | for (int i = (int)cSize - 2; i >= 0; i--) { 65 | G::mul(y, y, x); 66 | G::add(y, y, c[i]); 67 | } 68 | out = y; 69 | } 70 | 71 | } // mcl 72 | -------------------------------------------------------------------------------- /mcl/include/mcl/op.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief definition of Op 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | 11 | #ifndef MCL_MAX_BIT_SIZE 12 | #define MCL_MAX_BIT_SIZE 521 13 | #endif 14 | #ifdef __EMSCRIPTEN__ 15 | #define MCL_DONT_USE_XBYAK 16 | #define MCL_DONT_USE_OPENSSL 17 | #endif 18 | #if !defined(MCL_DONT_USE_XBYAK) && (defined(_WIN64) || defined(__x86_64__)) 19 | #define MCL_USE_XBYAK 20 | #endif 21 | 22 | namespace mcl { 23 | 24 | /* 25 | specifies available string format mode for X::setIoMode() 26 | // for Fp, Fp2, Fp6, Fp12 27 | default(0) : IoDec 28 | printable string(zero terminated, variable size) 29 | IoBin(2) | IoDec(10) | IoHex(16) | IoBinPrefix | IoHexPrefix 30 | 31 | byte string(not zero terminated, fixed size) 32 | IoArray | IoArrayRaw 33 | IoArray = IoFixedSizeByteSeq 34 | 35 | // for Ec 36 | affine(0) | IoEcCompY | IoComp 37 | default : affine 38 | 39 | affine and IoEcCompY are available with ioMode for Fp 40 | IoFixedSizeByteSeq ignores ioMode for Fp 41 | 42 | IoAuto 43 | dec or hex according to ios_base::fmtflags 44 | IoBin 45 | binary number([01]+) 46 | IoDec 47 | decimal number 48 | IoHex 49 | hexadecimal number([0-9a-fA-F]+) 50 | IoBinPrefix 51 | 0b + 52 | IoHexPrefix 53 | 0x + 54 | IoArray 55 | array of Unit(fixed size = Fp::getByteSize()) 56 | IoArrayRaw 57 | array of Unit(fixed size = Fp::getByteSize()) without Montgomery convresion 58 | 59 | // for Ec::setIoMode() 60 | IoEcAffine(default) 61 | "0" ; infinity 62 | "1 " ; affine coordinate 63 | 64 | IoEcProj 65 | "4" ; projective or jacobi coordinate 66 | 67 | IoEcCompY 68 | 1-bit y prepresentation of elliptic curve 69 | "2 " ; compressed for even y 70 | "3 " ; compressed for odd y 71 | 72 | IoFixedSizeByteSeq(fixed size = Fp::getByteSize()) 73 | use MSB of array of x for 1-bit y for prime p where (p % 8 != 0) 74 | [0] ; infinity 75 | ; for even y 76 | |1 ; for odd y ; |1 means set MSB of x 77 | */ 78 | enum IoMode { 79 | IoAuto = 0, // dec or hex according to ios_base::fmtflags 80 | IoBin = 2, // binary number without prefix 81 | IoDec = 10, // decimal number without prefix 82 | IoHex = 16, // hexadecimal number without prefix 83 | IoArray = 32, // array of Unit(fixed size) 84 | IoArrayRaw = 64, // raw array of Unit without Montgomery conversion 85 | IoPrefix = 128, // append '0b'(bin) or '0x'(hex) 86 | IoBinPrefix = IoBin | IoPrefix, 87 | IoHexPrefix = IoHex | IoPrefix, 88 | IoEcAffine = 0, // affine coordinate 89 | IoEcCompY = 256, // 1-bit y representation of elliptic curve 90 | IoFixedSizeByteSeq = 512, // use MBS for 1-bit y 91 | IoEcProj = 1024 // projective or jacobi coordinate 92 | }; 93 | 94 | namespace fp { 95 | 96 | const size_t UnitBitSize = sizeof(Unit) * 8; 97 | 98 | const size_t maxUnitSize = (MCL_MAX_BIT_SIZE + UnitBitSize - 1) / UnitBitSize; 99 | #define MCL_MAX_UNIT_SIZE ((MCL_MAX_BIT_SIZE + MCL_UNIT_BIT_SIZE - 1) / MCL_UNIT_BIT_SIZE) 100 | 101 | struct FpGenerator; 102 | struct Op; 103 | 104 | typedef void (*void1u)(Unit*); 105 | typedef void (*void2u)(Unit*, const Unit*); 106 | typedef void (*void2uI)(Unit*, const Unit*, Unit); 107 | typedef void (*void2uIu)(Unit*, const Unit*, Unit, const Unit*); 108 | typedef void (*void2uOp)(Unit*, const Unit*, const Op&); 109 | typedef void (*void3u)(Unit*, const Unit*, const Unit*); 110 | typedef void (*void4u)(Unit*, const Unit*, const Unit*, const Unit*); 111 | typedef int (*int2u)(Unit*, const Unit*); 112 | 113 | typedef Unit (*u1uII)(Unit*, Unit, Unit); 114 | typedef Unit (*u3u)(Unit*, const Unit*, const Unit*); 115 | 116 | struct Block { 117 | const Unit *p; // pointer to original FpT.v_ 118 | size_t n; 119 | Unit v_[maxUnitSize]; 120 | }; 121 | 122 | enum Mode { 123 | FP_AUTO, 124 | FP_GMP, 125 | FP_GMP_MONT, 126 | FP_LLVM, 127 | FP_LLVM_MONT, 128 | FP_XBYAK 129 | }; 130 | 131 | enum PrimeMode { 132 | PM_GENERIC = 0, 133 | PM_NICT_P192, 134 | PM_NICT_P521 135 | }; 136 | 137 | struct Op { 138 | /* 139 | don't change the layout of rp and p 140 | asm code assumes &rp + 1 == p 141 | */ 142 | Unit rp; 143 | Unit p[maxUnitSize]; 144 | mpz_class mp; 145 | uint32_t pmod4; 146 | mcl::SquareRoot sq; 147 | FpGenerator *fg; 148 | Unit half[maxUnitSize]; // (p + 1) / 2 149 | Unit oneRep[maxUnitSize]; // 1(=inv R if Montgomery) 150 | /* 151 | for Montgomery 152 | one = 1 153 | R = (1 << (N * sizeof(Unit) * 8)) % p 154 | R2 = (R * R) % p 155 | R3 = RR^3 156 | */ 157 | Unit one[maxUnitSize]; 158 | Unit R2[maxUnitSize]; 159 | Unit R3[maxUnitSize]; 160 | std::vector invTbl; 161 | size_t N; 162 | size_t bitSize; 163 | bool (*fp_isZero)(const Unit*); 164 | void1u fp_clear; 165 | void2u fp_copy; 166 | void2u fp_shr1; 167 | void3u fp_neg; 168 | void4u fp_add; 169 | void4u fp_sub; 170 | void4u fp_mul; 171 | void3u fp_sqr; 172 | void2uOp fp_invOp; 173 | void2uIu fp_mulUnit; // fpN1_mod + fp_mulUnitPre 174 | 175 | void3u fpDbl_mulPre; 176 | void2u fpDbl_sqrPre; 177 | int2u fp_preInv; 178 | void2uI fp_mulUnitPre; // z[N + 1] = x[N] * y 179 | void3u fpN1_mod; // y[N] = x[N + 1] % p[N] 180 | 181 | void4u fpDbl_add; 182 | void4u fpDbl_sub; 183 | void3u fpDbl_mod; 184 | 185 | u3u fp_addPre; // without modulo p 186 | u3u fp_subPre; // without modulo p 187 | u3u fpDbl_addPre; 188 | u3u fpDbl_subPre; 189 | /* 190 | for Fp2 = F[u] / (u^2 + 1) 191 | x = a + bu 192 | */ 193 | int xi_a; // xi = xi_a + u 194 | void3u fp2_add; 195 | void3u fp2_sub; 196 | void3u fp2_mul; 197 | void4u fp2_mulNF; 198 | void2u fp2_neg; 199 | void2u fp2_inv; 200 | void2u fp2_sqr; 201 | void2u fp2_mul_xi; 202 | 203 | PrimeMode primeMode; 204 | bool isFullBit; // true if bitSize % uniSize == 0 205 | bool isMont; // true if use Montgomery 206 | bool isFastMod; // true if modulo is fast 207 | 208 | Op() 209 | { 210 | clear(); 211 | fg = 0; 212 | } 213 | ~Op() 214 | { 215 | destroyFpGenerator(fg); 216 | } 217 | void clear() 218 | { 219 | rp = 0; 220 | memset(p, 0, sizeof(p)); 221 | mp = 0; 222 | pmod4 = 0; 223 | sq.clear(); 224 | // fg is not set 225 | memset(half, 0, sizeof(half)); 226 | memset(oneRep, 0, sizeof(oneRep)); 227 | memset(one, 0, sizeof(one)); 228 | memset(R2, 0, sizeof(R2)); 229 | memset(R3, 0, sizeof(R3)); 230 | invTbl.clear(); 231 | N = 0; 232 | bitSize = 0; 233 | fp_isZero = 0; 234 | fp_clear = 0; 235 | fp_copy = 0; 236 | fp_shr1 = 0; 237 | fp_neg = 0; 238 | fp_add = 0; 239 | fp_sub = 0; 240 | fp_mul = 0; 241 | fp_sqr = 0; 242 | fp_invOp = 0; 243 | fp_mulUnit = 0; 244 | 245 | fpDbl_mulPre = 0; 246 | fpDbl_sqrPre = 0; 247 | fp_preInv = 0; 248 | fp_mulUnitPre = 0; 249 | fpN1_mod = 0; 250 | 251 | fpDbl_add = 0; 252 | fpDbl_sub = 0; 253 | fpDbl_mod = 0; 254 | 255 | fp_addPre = 0; 256 | fp_subPre = 0; 257 | fpDbl_addPre = 0; 258 | fpDbl_subPre = 0; 259 | 260 | xi_a = 0; 261 | fp2_add = 0; 262 | fp2_sub = 0; 263 | fp2_mul = 0; 264 | fp2_mulNF = 0; 265 | fp2_neg = 0; 266 | fp2_inv = 0; 267 | fp2_sqr = 0; 268 | fp2_mul_xi = 0; 269 | 270 | primeMode = PM_GENERIC; 271 | isFullBit = false; 272 | isMont = false; 273 | isFastMod = false; 274 | } 275 | void fromMont(Unit* y, const Unit *x) const 276 | { 277 | /* 278 | M(x, y) = xyR^-1 279 | y = M(x, 1) = xR^-1 280 | */ 281 | fp_mul(y, x, one, p); 282 | } 283 | void toMont(Unit* y, const Unit *x) const 284 | { 285 | /* 286 | y = M(x, R2) = xR^2 R^-1 = xR 287 | */ 288 | fp_mul(y, x, R2, p); 289 | } 290 | void init(const std::string& mstr, size_t maxBitSize, Mode mode, size_t mclMaxBitSize = MCL_MAX_BIT_SIZE); 291 | void initFp2(int xi_a); 292 | static FpGenerator* createFpGenerator(); 293 | static void destroyFpGenerator(FpGenerator *fg); 294 | private: 295 | Op(const Op&); 296 | void operator=(const Op&); 297 | }; 298 | 299 | /* 300 | read data from is according to ioMode, 301 | and set x[0, n) with abs(buf[0, bufSize/sizeof(Unit))) 302 | @note byteSize is not num of Unit 303 | */ 304 | void streamToArray(bool *pIsMinus, Unit *x, size_t byteSize, std::istream& is, int ioMode); 305 | 306 | void arrayToStr(std::string& str, const Unit *x, size_t n, int ioMode); 307 | 308 | inline const char* getIoSeparator(int ioMode) 309 | { 310 | return (ioMode & (IoArray | IoArrayRaw | IoFixedSizeByteSeq)) ? "" : " "; 311 | } 312 | 313 | int detectIoMode(int ioMode, const std::ios_base& ios); 314 | 315 | inline void dump(const char *s, size_t n) 316 | { 317 | for (size_t i = 0; i < n; i++) { 318 | printf("%02x ", (uint8_t)s[i]); 319 | } 320 | printf("\n"); 321 | } 322 | 323 | inline void dump(const std::string& s) 324 | { 325 | dump(s.c_str(), s.size()); 326 | } 327 | 328 | } } // mcl::fp 329 | -------------------------------------------------------------------------------- /mcl/include/mcl/operator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief operator class 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | #include 11 | #ifdef _MSC_VER 12 | #ifndef MCL_FORCE_INLINE 13 | #define MCL_FORCE_INLINE __forceinline 14 | #endif 15 | #pragma warning(push) 16 | #pragma warning(disable : 4714) 17 | #else 18 | #ifndef MCL_FORCE_INLINE 19 | #define MCL_FORCE_INLINE __attribute__((always_inline)) 20 | #endif 21 | #endif 22 | 23 | namespace mcl { namespace fp { 24 | 25 | template 26 | struct Empty {}; 27 | 28 | /* 29 | T must have add, sub, mul, inv, neg 30 | */ 31 | template > 32 | struct Operator : E { 33 | template MCL_FORCE_INLINE T& operator+=(const S& rhs) { T::add(static_cast(*this), static_cast(*this), rhs); return static_cast(*this); } 34 | template MCL_FORCE_INLINE T& operator-=(const S& rhs) { T::sub(static_cast(*this), static_cast(*this), rhs); return static_cast(*this); } 35 | template friend MCL_FORCE_INLINE T operator+(const T& a, const S& b) { T c; T::add(c, a, b); return c; } 36 | template friend MCL_FORCE_INLINE T operator-(const T& a, const S& b) { T c; T::sub(c, a, b); return c; } 37 | template MCL_FORCE_INLINE T& operator*=(const S& rhs) { T::mul(static_cast(*this), static_cast(*this), rhs); return static_cast(*this); } 38 | template friend MCL_FORCE_INLINE T operator*(const T& a, const S& b) { T c; T::mul(c, a, b); return c; } 39 | MCL_FORCE_INLINE T& operator/=(const T& rhs) { T c; T::inv(c, rhs); T::mul(static_cast(*this), static_cast(*this), c); return static_cast(*this); } 40 | static MCL_FORCE_INLINE void div(T& c, const T& a, const T& b) { T t; T::inv(t, b); T::mul(c, a, t); } 41 | friend MCL_FORCE_INLINE T operator/(const T& a, const T& b) { T c; T::inv(c, b); c *= a; return c; } 42 | MCL_FORCE_INLINE T operator-() const { T c; T::neg(c, static_cast(*this)); return c; } 43 | template class FpT> 44 | static void pow(T& z, const T& x, const FpT& y) 45 | { 46 | fp::Block b; 47 | y.getBlock(b); 48 | powArray(z, x, b.p, b.n, false, false); 49 | } 50 | template class FpT> 51 | static void powGeneric(T& z, const T& x, const FpT& y) 52 | { 53 | fp::Block b; 54 | y.getBlock(b); 55 | powArrayBase(z, x, b.p, b.n, false, false); 56 | } 57 | template class FpT> 58 | static void powCT(T& z, const T& x, const FpT& y) 59 | { 60 | fp::Block b; 61 | y.getBlock(b); 62 | powArray(z, x, b.p, b.n, false, true); 63 | } 64 | static void pow(T& z, const T& x, int y) 65 | { 66 | const Unit u = abs(y); 67 | powArray(z, x, &u, 1, y < 0, false); 68 | } 69 | static void pow(T& z, const T& x, const mpz_class& y) 70 | { 71 | powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, false); 72 | } 73 | static void powGeneric(T& z, const T& x, const mpz_class& y) 74 | { 75 | powArrayBase(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, false); 76 | } 77 | static void powCT(T& z, const T& x, const mpz_class& y) 78 | { 79 | powArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, true); 80 | } 81 | static void setPowArrayGLV(void f(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime)) 82 | { 83 | powArrayGLV = f; 84 | } 85 | private: 86 | static void (*powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime); 87 | static void powArray(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime) 88 | { 89 | if (powArrayGLV && (constTime || yn > 1)) { 90 | powArrayGLV(z, x, y, yn, isNegative, constTime); 91 | return; 92 | } 93 | powArrayBase(z, x, y, yn, isNegative, constTime); 94 | } 95 | static void powArrayBase(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime) 96 | { 97 | T tmp; 98 | const T *px = &x; 99 | if (&z == &x) { 100 | tmp = x; 101 | px = &tmp; 102 | } 103 | z = 1; 104 | fp::powGeneric(z, *px, y, yn, T::mul, T::sqr, (void (*)(T&, const T&))0, constTime ? T::BaseFp::getBitSize() : 0); 105 | if (isNegative) { 106 | T::inv(z, z); 107 | } 108 | } 109 | }; 110 | 111 | template 112 | void (*Operator::powArrayGLV)(T& z, const T& x, const Unit *y, size_t yn, bool isNegative, bool constTime); 113 | 114 | } } // mcl::fp 115 | 116 | -------------------------------------------------------------------------------- /mcl/include/mcl/random.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief random generator 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | 10 | #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 11 | #include 12 | #else 13 | #include 14 | #endif 15 | 16 | namespace mcl { 17 | 18 | #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 19 | inline std::random_device& getRandomGenerator() 20 | { 21 | static std::random_device rd; 22 | return rd; 23 | } 24 | #else 25 | 26 | inline cybozu::RandomGenerator& getRandomGenerator() 27 | { 28 | static cybozu::RandomGenerator rg; 29 | return rg; 30 | } 31 | 32 | #endif 33 | 34 | } // mcl 35 | -------------------------------------------------------------------------------- /mcl/include/mcl/util.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief functions for T[] 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | 11 | #ifdef _MSC_VER 12 | #pragma warning(push) 13 | #pragma warning(disable : 4456) 14 | #pragma warning(disable : 4459) 15 | #endif 16 | 17 | namespace mcl { namespace fp { 18 | 19 | /* 20 | get pp such that p * pp = -1 mod M, 21 | where p is prime and M = 1 << 64(or 32). 22 | @param pLow [in] p mod M 23 | */ 24 | template 25 | T getMontgomeryCoeff(T pLow) 26 | { 27 | T ret = 0; 28 | T t = 0; 29 | T x = 1; 30 | for (size_t i = 0; i < sizeof(T) * 8; i++) { 31 | if ((t & 1) == 0) { 32 | t += pLow; 33 | ret += x; 34 | } 35 | t >>= 1; 36 | x <<= 1; 37 | } 38 | return ret; 39 | } 40 | 41 | template 42 | int compareArray(const T* x, const T* y, size_t n) 43 | { 44 | for (size_t i = n - 1; i != size_t(-1); i--) { 45 | T a = x[i]; 46 | T b = y[i]; 47 | if (a != b) return a < b ? -1 : 1; 48 | } 49 | return 0; 50 | } 51 | 52 | template 53 | bool isLessArray(const T *x, const T* y, size_t n) 54 | { 55 | for (size_t i = n - 1; i != size_t(-1); i--) { 56 | T a = x[i]; 57 | T b = y[i]; 58 | if (a != b) return a < b; 59 | } 60 | return false; 61 | } 62 | 63 | template 64 | bool isGreaterOrEqualArray(const T *x, const T* y, size_t n) 65 | { 66 | return !isLessArray(x, y, n); 67 | } 68 | 69 | template 70 | bool isLessOrEqualArray(const T *x, const T* y, size_t n) 71 | { 72 | for (size_t i = n - 1; i != size_t(-1); i--) { 73 | T a = x[i]; 74 | T b = y[i]; 75 | if (a != b) return a < b; 76 | } 77 | return true; 78 | } 79 | 80 | template 81 | bool isGreaterArray(const T *x, const T* y, size_t n) 82 | { 83 | return !isLessOrEqualArray(x, y, n); 84 | } 85 | 86 | template 87 | bool isEqualArray(const T* x, const T* y, size_t n) 88 | { 89 | for (size_t i = 0; i < n; i++) { 90 | if (x[i] != y[i]) return false; 91 | } 92 | return true; 93 | } 94 | 95 | template 96 | bool isZeroArray(const T *x, size_t n) 97 | { 98 | for (size_t i = 0; i < n; i++) { 99 | if (x[i]) return false; 100 | } 101 | return true; 102 | } 103 | 104 | template 105 | void clearArray(T *x, size_t begin, size_t end) 106 | { 107 | for (size_t i = begin; i < end; i++) x[i] = 0; 108 | } 109 | 110 | template 111 | void copyArray(T *y, const T *x, size_t n) 112 | { 113 | for (size_t i = 0; i < n; i++) y[i] = x[i]; 114 | } 115 | 116 | /* 117 | x &= (1 << bitSize) - 1 118 | */ 119 | template 120 | void maskArray(T *x, size_t n, size_t bitSize) 121 | { 122 | const size_t TbitSize = sizeof(T) * 8; 123 | assert(bitSize <= TbitSize * n); 124 | const size_t q = bitSize / TbitSize; 125 | const size_t r = bitSize % TbitSize; 126 | if (r) { 127 | x[q] &= (T(1) << r) - 1; 128 | clearArray(x, q + 1, n); 129 | } else { 130 | clearArray(x, q, n); 131 | } 132 | } 133 | 134 | /* 135 | return non zero size of x[] 136 | return 1 if x[] == 0 137 | */ 138 | template 139 | size_t getNonZeroArraySize(const T *x, size_t n) 140 | { 141 | assert(n > 0); 142 | while (n > 0) { 143 | if (x[n - 1]) return n; 144 | n--; 145 | } 146 | return 1; 147 | } 148 | 149 | namespace impl { 150 | 151 | template 152 | static void readN(T* out, size_t n, RG& rg) 153 | { 154 | if (sizeof(T) == 8) { 155 | for (size_t i = 0; i < n; i++) { 156 | T L = rg(); 157 | T H = rg(); 158 | out[i] = L | (uint64_t(H) << 32); 159 | } 160 | } else { 161 | for (size_t i = 0; i < n; i++) { 162 | out[i] = rg(); 163 | } 164 | } 165 | } 166 | 167 | } // impl 168 | /* 169 | get random value less than in[] 170 | n = (bitSize + sizeof(T) * 8) / (sizeof(T) * 8) 171 | input in[0..n) 172 | output out[n..n) 173 | 0 <= out < in 174 | */ 175 | template 176 | void getRandVal(T *out, RG& rg, const T *in, size_t bitSize) 177 | { 178 | const size_t TbitSize = sizeof(T) * 8; 179 | const size_t n = (bitSize + TbitSize - 1) / TbitSize; 180 | const size_t rem = bitSize & (TbitSize - 1); 181 | for (;;) { 182 | impl::readN(out, n, rg); 183 | // rg.read(out, n); 184 | if (rem > 0) out[n - 1] &= (T(1) << rem) - 1; 185 | if (isLessArray(out, in, n)) return; 186 | } 187 | } 188 | 189 | /* 190 | @param out [inout] : set element of G ; out = x^y[] 191 | @param x [in] 192 | @param y [in] 193 | @param n [in] size of y[] 194 | @param limitBit [in] const time version if the value is positive 195 | @note &out != x and out = the unit element of G 196 | */ 197 | template 198 | void powGeneric(G& out, const G& x, const T *y, size_t n, const Mul& mul, const Sqr& sqr, void normalize(G&, const G&), size_t limitBit = 0) 199 | { 200 | assert(&out != &x); 201 | G tbl[4]; // tbl = { discard, x, x^2, x^3 } 202 | T v; 203 | bool constTime = limitBit > 0; 204 | int maxBit = 0; 205 | int m = 0; 206 | while (n > 0) { 207 | if (y[n - 1]) break; 208 | n--; 209 | } 210 | if (n == 0) { 211 | if (constTime) goto DummyLoop; 212 | return; 213 | } 214 | if (!constTime && n == 1) { 215 | switch (y[0]) { 216 | case 1: 217 | out = x; 218 | return; 219 | case 2: 220 | sqr(out, x); 221 | return; 222 | case 3: 223 | sqr(out, x); 224 | mul(out, out, x); 225 | return; 226 | case 4: 227 | sqr(out, x); 228 | sqr(out, out); 229 | return; 230 | } 231 | } 232 | if (normalize != 0) { 233 | normalize(tbl[0], x); 234 | } else { 235 | tbl[0] = x; 236 | } 237 | tbl[1] = tbl[0]; 238 | sqr(tbl[2], tbl[1]); 239 | if (normalize != 0) { normalize(tbl[2], tbl[2]); } 240 | mul(tbl[3], tbl[2], x); 241 | if (normalize != 0) { normalize(tbl[3], tbl[3]); } 242 | v = y[n - 1]; 243 | assert(v); 244 | m = cybozu::bsr(v); 245 | maxBit = int(m + (n - 1) * sizeof(T) * 8); 246 | if (m & 1) { 247 | m--; 248 | T idx = (v >> m) & 3; 249 | assert(idx > 0); 250 | out = tbl[idx]; 251 | } else { 252 | out = x; 253 | } 254 | for (int i = (int)n - 1; i >= 0; i--) { 255 | T v = y[i]; 256 | for (int j = m - 2; j >= 0; j -= 2) { 257 | sqr(out, out); 258 | sqr(out, out); 259 | T idx = (v >> j) & 3; 260 | if (idx == 0) { 261 | if (constTime) mul(tbl[0], tbl[0], tbl[1]); 262 | } else { 263 | mul(out, out, tbl[idx]); 264 | } 265 | } 266 | m = (int)sizeof(T) * 8; 267 | } 268 | DummyLoop: 269 | if (!constTime) return; 270 | G D = out; 271 | for (size_t i = maxBit + 1; i < limitBit; i += 2) { 272 | sqr(D, D); 273 | sqr(D, D); 274 | mul(D, D, tbl[1]); 275 | } 276 | } 277 | 278 | /* 279 | shortcut of multiplication by Unit 280 | */ 281 | template 282 | bool mulSmallUnit(T& z, const T& x, U y) 283 | { 284 | switch (y) { 285 | case 0: z.clear(); break; 286 | case 1: z = x; break; 287 | case 2: T::add(z, x, x); break; 288 | case 3: { T t; T::add(t, x, x); T::add(z, t, x); break; } 289 | case 4: T::add(z, x, x); T::add(z, z, z); break; 290 | case 5: { T t; T::add(t, x, x); T::add(t, t, t); T::add(z, t, x); break; } 291 | case 6: { T t; T::add(t, x, x); T::add(t, t, x); T::add(z, t, t); break; } 292 | case 7: { T t; T::add(t, x, x); T::add(t, t, t); T::add(t, t, t); T::sub(z, t, x); break; } 293 | case 8: T::add(z, x, x); T::add(z, z, z); T::add(z, z, z); break; 294 | 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; } 295 | 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; } 296 | default: 297 | return false; 298 | } 299 | return true; 300 | } 301 | 302 | } } // mcl::fp 303 | 304 | #ifdef _MSC_VER 305 | #pragma warning(pop) 306 | #endif 307 | -------------------------------------------------------------------------------- /mcl/lib/.emptydir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfinity-side-projects/bn/645379f3aab6386bf5f490104584b4a91344ab56/mcl/lib/.emptydir -------------------------------------------------------------------------------- /mcl/obj/.emptydir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfinity-side-projects/bn/645379f3aab6386bf5f490104584b4a91344ab56/mcl/obj/.emptydir -------------------------------------------------------------------------------- /mcl/src/asm/.emptydir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfinity-side-projects/bn/645379f3aab6386bf5f490104584b4a91344ab56/mcl/src/asm/.emptydir -------------------------------------------------------------------------------- /mcl/src/bn_c384.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | implementation of mclBn_* apis 3 | */ 4 | #define MCLBN_FP_UNIT_SIZE 6 5 | #include "bn_c_impl.hpp" 6 | 7 | -------------------------------------------------------------------------------- /mcl/src/conversion.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | /** 7 | @file 8 | @brief convertion from T[] to str2, str16 9 | @author MITSUNARI Shigeo(@herumi) 10 | @license modified new BSD license 11 | http://opensource.org/licenses/BSD-3-Clause 12 | */ 13 | 14 | namespace mcl { namespace fp { 15 | 16 | /* 17 | convert x[0..n) to hex string 18 | start "0x" if withPrefix 19 | */ 20 | template 21 | void toStr16(std::string& str, const T *x, size_t n, bool withPrefix = false) 22 | { 23 | size_t fullN = 0; 24 | if (n > 1) { 25 | size_t pos = n - 1; 26 | while (pos > 0) { 27 | if (x[pos]) break; 28 | pos--; 29 | } 30 | if (pos > 0) fullN = pos; 31 | } 32 | const T v = n == 0 ? 0 : x[fullN]; 33 | const size_t topLen = cybozu::getHexLength(v); 34 | const size_t startPos = withPrefix ? 2 : 0; 35 | const size_t lenT = sizeof(T) * 2; 36 | str.resize(startPos + fullN * lenT + topLen); 37 | if (withPrefix) { 38 | str[0] = '0'; 39 | str[1] = 'x'; 40 | } 41 | cybozu::itohex(&str[startPos], topLen, v, false); 42 | for (size_t i = 0; i < fullN; i++) { 43 | cybozu::itohex(&str[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i], false); 44 | } 45 | } 46 | 47 | /* 48 | convert x[0..n) to bin string 49 | start "0b" if withPrefix 50 | */ 51 | template 52 | void toStr2(std::string& str, const T *x, size_t n, bool withPrefix) 53 | { 54 | size_t fullN = 0; 55 | if (n > 1) { 56 | size_t pos = n - 1; 57 | while (pos > 0) { 58 | if (x[pos]) break; 59 | pos--; 60 | } 61 | if (pos > 0) fullN = pos; 62 | } 63 | const T v = n == 0 ? 0 : x[fullN]; 64 | const size_t topLen = cybozu::getBinLength(v); 65 | const size_t startPos = withPrefix ? 2 : 0; 66 | const size_t lenT = sizeof(T) * 8; 67 | str.resize(startPos + fullN * lenT + topLen); 68 | if (withPrefix) { 69 | str[0] = '0'; 70 | str[1] = 'b'; 71 | } 72 | cybozu::itobin(&str[startPos], topLen, v); 73 | for (size_t i = 0; i < fullN; i++) { 74 | cybozu::itobin(&str[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i]); 75 | } 76 | } 77 | 78 | /* 79 | convert hex string to x[0..xn) 80 | hex string = [0-9a-fA-F]+ 81 | */ 82 | template 83 | void fromStr16(T *x, size_t xn, const char *str, size_t strLen) 84 | { 85 | if (strLen == 0) throw cybozu::Exception("fp:fromStr16:strLen is zero"); 86 | const size_t unitLen = sizeof(T) * 2; 87 | const size_t q = strLen / unitLen; 88 | const size_t r = strLen % unitLen; 89 | const size_t requireSize = q + (r ? 1 : 0); 90 | if (xn < requireSize) throw cybozu::Exception("fp:fromStr16:short size") << xn << requireSize; 91 | for (size_t i = 0; i < q; i++) { 92 | bool b; 93 | x[i] = cybozu::hextoi(&b, &str[r + (q - 1 - i) * unitLen], unitLen); 94 | if (!b) throw cybozu::Exception("fp:fromStr16:bad char") << cybozu::exception::makeString(str, strLen); 95 | } 96 | if (r) { 97 | bool b; 98 | x[q] = cybozu::hextoi(&b, str, r); 99 | if (!b) throw cybozu::Exception("fp:fromStr16:bad char") << cybozu::exception::makeString(str, strLen); 100 | } 101 | for (size_t i = requireSize; i < xn; i++) x[i] = 0; 102 | } 103 | 104 | 105 | } } // mcl::fp 106 | -------------------------------------------------------------------------------- /mcl/src/low_func_llvm.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace mcl { namespace fp { 4 | 5 | template<> 6 | struct EnableKaratsuba { 7 | #if MCL_SIZEOF_UNIT == 4 8 | static const size_t minMulN = 10; 9 | static const size_t minSqrN = 10; 10 | #else 11 | static const size_t minMulN = 8; 12 | static const size_t minSqrN = 6; 13 | #endif 14 | }; 15 | 16 | #if MCL_SIZEOF_UNIT == 4 17 | #define MCL_GMP_IS_FASTER_THAN_LLVM // QQQ : check later 18 | #endif 19 | 20 | #ifdef MCL_GMP_IS_FASTER_THAN_LLVM 21 | #define MCL_DEF_MUL(n, tag, suf) 22 | #else 23 | #define MCL_DEF_MUL(n, tag, suf) \ 24 | template<>const void3u MulPreCore::f = &mcl_fpDbl_mulPre ## n ## suf; \ 25 | template<>const void2u SqrPreCore::f = &mcl_fpDbl_sqrPre ## n ## suf; 26 | #endif 27 | 28 | #define MCL_DEF_LLVM_FUNC2(n, tag, suf) \ 29 | template<>const u3u AddPre::f = &mcl_fp_addPre ## n ## suf; \ 30 | template<>const u3u SubPre::f = &mcl_fp_subPre ## n ## suf; \ 31 | template<>const void2u Shr1::f = &mcl_fp_shr1_ ## n ## suf; \ 32 | MCL_DEF_MUL(n, tag, suf) \ 33 | template<>const void2uI MulUnitPre::f = &mcl_fp_mulUnitPre ## n ## suf; \ 34 | template<>const void4u Add::f = &mcl_fp_add ## n ## suf; \ 35 | template<>const void4u Add::f = &mcl_fp_addNF ## n ## suf; \ 36 | template<>const void4u Sub::f = &mcl_fp_sub ## n ## suf; \ 37 | template<>const void4u Sub::f = &mcl_fp_subNF ## n ## suf; \ 38 | template<>const void4u Mont::f = &mcl_fp_mont ## n ## suf; \ 39 | template<>const void4u Mont::f = &mcl_fp_montNF ## n ## suf; \ 40 | template<>const void3u MontRed::f = &mcl_fp_montRed ## n ## suf; \ 41 | template<>const void4u DblAdd::f = &mcl_fpDbl_add ## n ## suf; \ 42 | template<>const void4u DblSub::f = &mcl_fpDbl_sub ## n ## suf; \ 43 | 44 | #if CYBOZU_HOST == CYBOZU_HOST_INTEL 45 | #define MCL_DEF_LLVM_FUNC(n) \ 46 | MCL_DEF_LLVM_FUNC2(n, Ltag, L) \ 47 | MCL_DEF_LLVM_FUNC2(n, LBMI2tag, Lbmi2) 48 | #else 49 | #define MCL_DEF_LLVM_FUNC(n) \ 50 | MCL_DEF_LLVM_FUNC2(n, Ltag, L) 51 | #endif 52 | 53 | MCL_DEF_LLVM_FUNC(1) 54 | MCL_DEF_LLVM_FUNC(2) 55 | MCL_DEF_LLVM_FUNC(3) 56 | MCL_DEF_LLVM_FUNC(4) 57 | #if MCL_MAX_UNIT_SIZE >= 6 58 | MCL_DEF_LLVM_FUNC(5) 59 | MCL_DEF_LLVM_FUNC(6) 60 | #endif 61 | #if MCL_MAX_UNIT_SIZE >= 8 62 | MCL_DEF_LLVM_FUNC(7) 63 | MCL_DEF_LLVM_FUNC(8) 64 | #endif 65 | #if MCL_MAX_UNIT_SIZE >= 9 66 | MCL_DEF_LLVM_FUNC(9) 67 | #endif 68 | #if MCL_MAX_UNIT_SIZE >= 10 69 | MCL_DEF_LLVM_FUNC(10) 70 | #endif 71 | #if MCL_MAX_UNIT_SIZE >= 12 72 | MCL_DEF_LLVM_FUNC(11) 73 | MCL_DEF_LLVM_FUNC(12) 74 | #endif 75 | #if MCL_MAX_UNIT_SIZE >= 14 76 | MCL_DEF_LLVM_FUNC(13) 77 | MCL_DEF_LLVM_FUNC(14) 78 | #endif 79 | #if MCL_MAX_UNIT_SIZE >= 16 80 | MCL_DEF_LLVM_FUNC(15) 81 | #if MCL_SIZEOF_UNIT == 4 82 | MCL_DEF_LLVM_FUNC(16) 83 | #else 84 | /// QQQ : check speed 85 | template<>const void3u MontRed<16, Ltag>::f = &mcl_fp_montRed16L; 86 | template<>const void3u MontRed<16, LBMI2tag>::f = &mcl_fp_montRed16Lbmi2; 87 | #endif 88 | #endif 89 | #if MCL_MAX_UNIT_SIZE >= 17 90 | MCL_DEF_LLVM_FUNC(17) 91 | #endif 92 | 93 | } } // mcl::fp 94 | 95 | -------------------------------------------------------------------------------- /mcl/src/proto.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | @file 4 | @brief prototype of asm function 5 | @author MITSUNARI Shigeo(@herumi) 6 | @license modified new BSD license 7 | http://opensource.org/licenses/BSD-3-Clause 8 | */ 9 | #include 10 | 11 | #define MCL_FP_DEF_FUNC_SUB(n, suf) \ 12 | void mcl_fp_add ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y, const mcl::fp::Unit* p); \ 13 | void mcl_fp_addNF ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y, const mcl::fp::Unit* p); \ 14 | void mcl_fp_sub ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y, const mcl::fp::Unit* p); \ 15 | void mcl_fp_subNF ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y, const mcl::fp::Unit* p); \ 16 | void mcl_fp_shr1_ ## n ## suf(mcl::fp::Unit*y, const mcl::fp::Unit* x); \ 17 | mcl::fp::Unit mcl_fp_addPre ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y); \ 18 | mcl::fp::Unit mcl_fp_subPre ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y); \ 19 | void mcl_fp_mulUnitPre ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, mcl::fp::Unit y); \ 20 | void mcl_fpDbl_mulPre ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y); \ 21 | void mcl_fpDbl_sqrPre ## n ## suf(mcl::fp::Unit* y, const mcl::fp::Unit* x); \ 22 | void mcl_fp_mont ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y, const mcl::fp::Unit* p); \ 23 | void mcl_fp_montNF ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y, const mcl::fp::Unit* p); \ 24 | void mcl_fp_montRed ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* xy, const mcl::fp::Unit* p); \ 25 | void mcl_fpDbl_add ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y, const mcl::fp::Unit* p); \ 26 | void mcl_fpDbl_sub ## n ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y, const mcl::fp::Unit* p); 27 | 28 | #define MCL_FP_DEF_FUNC(n) \ 29 | MCL_FP_DEF_FUNC_SUB(n, L) \ 30 | MCL_FP_DEF_FUNC_SUB(n, Lbmi2) 31 | 32 | #define MCL_FP_DEF_FUNC_SPECIAL(suf) \ 33 | void mcl_fpDbl_mod_NIST_P192 ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* xy, const mcl::fp::Unit* /* dummy */); \ 34 | void mcl_fp_mulNIST_P192 ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* x, const mcl::fp::Unit* y, const mcl::fp::Unit* /* dummy */); \ 35 | void mcl_fp_sqr_NIST_P192 ## suf(mcl::fp::Unit* y, const mcl::fp::Unit* x, const mcl::fp::Unit* /* dummy */); \ 36 | void mcl_fpDbl_mod_NIST_P521 ## suf(mcl::fp::Unit* z, const mcl::fp::Unit* xy, const mcl::fp::Unit* /* dummy */); 37 | 38 | extern "C" { 39 | 40 | MCL_FP_DEF_FUNC(1) 41 | MCL_FP_DEF_FUNC(2) 42 | MCL_FP_DEF_FUNC(3) 43 | MCL_FP_DEF_FUNC(4) 44 | #if MCL_MAX_UNIT_SIZE >= 6 45 | MCL_FP_DEF_FUNC(5) 46 | MCL_FP_DEF_FUNC(6) 47 | #endif 48 | #if MCL_MAX_UNIT_SIZE >= 8 49 | MCL_FP_DEF_FUNC(7) 50 | MCL_FP_DEF_FUNC(8) 51 | #endif 52 | #if MCL_MAX_UNIT_SIZE >= 9 53 | MCL_FP_DEF_FUNC(9) 54 | #endif 55 | #if MCL_MAX_UNIT_SIZE >= 10 56 | MCL_FP_DEF_FUNC(10) 57 | #endif 58 | #if MCL_MAX_UNIT_SIZE >= 12 59 | MCL_FP_DEF_FUNC(11) 60 | MCL_FP_DEF_FUNC(12) 61 | #endif 62 | #if MCL_MAX_UNIT_SIZE >= 14 63 | MCL_FP_DEF_FUNC(13) 64 | MCL_FP_DEF_FUNC(14) 65 | #endif 66 | #if MCL_MAX_UNIT_SIZE >= 16 67 | MCL_FP_DEF_FUNC(15) 68 | MCL_FP_DEF_FUNC(16) 69 | #endif 70 | #if MCL_MAX_UNIT_SIZE >= 17 71 | MCL_FP_DEF_FUNC(17) 72 | #endif 73 | 74 | MCL_FP_DEF_FUNC_SPECIAL(L) 75 | MCL_FP_DEF_FUNC_SPECIAL(Lbmi2) 76 | 77 | } 78 | 79 | #undef MCL_FP_DEF_FUNC_SUB 80 | #undef MCL_FP_DEF_FUNC 81 | 82 | -------------------------------------------------------------------------------- /mcl/test/bn_c384_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace mcl::bn384; 3 | #define MCLBN_DEFINE_STRUCT 4 | #define MCLBN_FP_UNIT_SIZE 6 5 | #include "bn_c_test.hpp" 6 | 7 | -------------------------------------------------------------------------------- /mcl/test/bn_c_test.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | include from bn_if256_test.cpp and bn_if384_test.cpp 3 | */ 4 | #include 5 | #include 6 | #include 7 | 8 | template 9 | std::ostream& dump(std::ostream& os, const uint64_t (&x)[N]) 10 | { 11 | for (size_t i = 0; i < N; i++) { 12 | char buf[64]; 13 | CYBOZU_SNPRINTF(buf, sizeof(buf), "%016llx", (long long)x[i]); 14 | os << buf; 15 | } 16 | return os; 17 | } 18 | 19 | CYBOZU_TEST_AUTO(init) 20 | { 21 | int ret; 22 | CYBOZU_TEST_EQUAL(sizeof(mclBnFr), sizeof(Fr)); 23 | CYBOZU_TEST_EQUAL(sizeof(mclBnG1), sizeof(G1)); 24 | CYBOZU_TEST_EQUAL(sizeof(mclBnG2), sizeof(G2)); 25 | CYBOZU_TEST_EQUAL(sizeof(mclBnGT), sizeof(Fp12)); 26 | 27 | // ret = mclBn_setErrFile("stderr"); 28 | // CYBOZU_TEST_EQUAL(ret, 0); 29 | 30 | #if MCLBN_FP_UNIT_SIZE == 4 31 | printf("test MCLBN_curveFp254BNb %d\n", MCLBN_FP_UNIT_SIZE); 32 | ret = mclBn_init(mclBn_CurveFp254BNb, MCLBN_FP_UNIT_SIZE); 33 | #else 34 | printf("test MCLBN_curveFp382_1 %d\n", MCLBN_FP_UNIT_SIZE); 35 | ret = mclBn_init(mclBn_CurveFp382_1, MCLBN_FP_UNIT_SIZE); 36 | #endif 37 | CYBOZU_TEST_EQUAL(ret, 0); 38 | } 39 | 40 | CYBOZU_TEST_AUTO(Fr) 41 | { 42 | mclBnFr x, y; 43 | memset(&x, 0xff, sizeof(x)); 44 | CYBOZU_TEST_ASSERT(!mclBnFr_isValid(&x)); 45 | memset(&x, 1, sizeof(x)); 46 | CYBOZU_TEST_ASSERT(mclBnFr_isValid(&x)); 47 | CYBOZU_TEST_ASSERT(!mclBnFr_isZero(&x)); 48 | 49 | mclBnFr_clear(&x); 50 | CYBOZU_TEST_ASSERT(mclBnFr_isZero(&x)); 51 | 52 | mclBnFr_setInt(&x, 1); 53 | CYBOZU_TEST_ASSERT(mclBnFr_isOne(&x)); 54 | 55 | mclBnFr_setInt(&y, -1); 56 | CYBOZU_TEST_ASSERT(!mclBnFr_isEqual(&x, &y)); 57 | 58 | y = x; 59 | CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y)); 60 | 61 | mclBnFr_setHashOf(&x, "", 0); 62 | mclBnFr_setHashOf(&y, "abc", 3); 63 | CYBOZU_TEST_ASSERT(!mclBnFr_isEqual(&x, &y)); 64 | mclBnFr_setHashOf(&x, "abc", 3); 65 | CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y)); 66 | 67 | char buf[1024]; 68 | mclBnFr_setInt(&x, 12345678); 69 | size_t size; 70 | size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); 71 | CYBOZU_TEST_EQUAL(size, 8); 72 | CYBOZU_TEST_EQUAL(buf, "12345678"); 73 | 74 | mclBnFr_setInt(&x, -7654321); 75 | mclBnFr_neg(&x, &x); 76 | size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); 77 | CYBOZU_TEST_EQUAL(size, 7); 78 | CYBOZU_TEST_EQUAL(buf, "7654321"); 79 | 80 | mclBnFr_setInt(&y, 123 - 7654321); 81 | mclBnFr_add(&x, &x, &y); 82 | size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); 83 | CYBOZU_TEST_EQUAL(size, 3); 84 | CYBOZU_TEST_EQUAL(buf, "123"); 85 | 86 | mclBnFr_setInt(&y, 100); 87 | mclBnFr_sub(&x, &x, &y); 88 | size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); 89 | CYBOZU_TEST_EQUAL(size, 2); 90 | CYBOZU_TEST_EQUAL(buf, "23"); 91 | 92 | mclBnFr_mul(&x, &x, &y); 93 | size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); 94 | CYBOZU_TEST_EQUAL(size, 4); 95 | CYBOZU_TEST_EQUAL(buf, "2300"); 96 | 97 | mclBnFr_div(&x, &x, &y); 98 | size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); 99 | CYBOZU_TEST_EQUAL(size, 2); 100 | CYBOZU_TEST_EQUAL(buf, "23"); 101 | 102 | const char *s = "12345678901234567"; 103 | CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&x, s, strlen(s), 10)); 104 | s = "20000000000000000"; 105 | CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&y, s, strlen(s), 10)); 106 | mclBnFr_add(&x, &x, &y); 107 | size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); 108 | CYBOZU_TEST_EQUAL(size, 17); 109 | CYBOZU_TEST_EQUAL(buf, "32345678901234567"); 110 | 111 | mclBnFr_setInt(&x, 1); 112 | mclBnFr_neg(&x, &x); 113 | size = mclBnFr_getStr(buf, sizeof(buf), &x, 10); 114 | CYBOZU_TEST_ASSERT(size > 0); 115 | CYBOZU_TEST_EQUAL(size, strlen(buf)); 116 | CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&y, buf, size, 10)); 117 | CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y)); 118 | } 119 | 120 | CYBOZU_TEST_AUTO(G1) 121 | { 122 | mclBnG1 x, y, z; 123 | memset(&x, 0xff, sizeof(x)); 124 | CYBOZU_TEST_ASSERT(!mclBnG1_isValid(&x)); 125 | mclBnG1_clear(&x); 126 | CYBOZU_TEST_ASSERT(mclBnG1_isValid(&x)); 127 | CYBOZU_TEST_ASSERT(mclBnG1_isZero(&x)); 128 | 129 | CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&y, "abc", 3)); 130 | 131 | char buf[1024]; 132 | size_t size; 133 | size = mclBnG1_getStr(buf, sizeof(buf), &x, 10); 134 | CYBOZU_TEST_ASSERT(size > 0); 135 | CYBOZU_TEST_EQUAL(size, strlen(buf)); 136 | CYBOZU_TEST_ASSERT(!mclBnG1_setStr(&y, buf, strlen(buf), 10)); 137 | CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &y)); 138 | 139 | mclBnG1_neg(&x, &x); 140 | mclBnG1_add(&x, &x, &y); 141 | CYBOZU_TEST_ASSERT(mclBnG1_isZero(&x)); 142 | 143 | mclBnG1_dbl(&x, &y); // x = 2y 144 | mclBnG1_add(&z, &y, &y); 145 | CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z)); 146 | mclBnG1_add(&z, &z, &y); // z = 3y 147 | mclBnFr n; 148 | mclBnFr_setInt(&n, 3); 149 | mclBnG1_mul(&x, &y, &n); // x = 3y 150 | CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z)); 151 | mclBnG1_sub(&x, &x, &y); // x = 2y 152 | 153 | mclBnFr_setInt(&n, 2); 154 | mclBnG1_mul(&z, &y, &n); // z = 2y 155 | CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z)); 156 | } 157 | 158 | CYBOZU_TEST_AUTO(G2) 159 | { 160 | mclBnG2 x, y, z; 161 | memset(&x, 0xff, sizeof(x)); 162 | CYBOZU_TEST_ASSERT(!mclBnG2_isValid(&x)); 163 | mclBnG2_clear(&x); 164 | CYBOZU_TEST_ASSERT(mclBnG2_isValid(&x)); 165 | CYBOZU_TEST_ASSERT(mclBnG2_isZero(&x)); 166 | 167 | CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&x, "abc", 3)); 168 | 169 | char buf[1024]; 170 | size_t size; 171 | size = mclBnG2_getStr(buf, sizeof(buf), &x, 10); 172 | CYBOZU_TEST_ASSERT(size > 0); 173 | CYBOZU_TEST_EQUAL(size, strlen(buf)); 174 | CYBOZU_TEST_ASSERT(!mclBnG2_setStr(&y, buf, strlen(buf), 10)); 175 | CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &y)); 176 | 177 | mclBnG2_neg(&x, &x); 178 | mclBnG2_add(&x, &x, &y); 179 | CYBOZU_TEST_ASSERT(mclBnG2_isZero(&x)); 180 | 181 | mclBnG2_dbl(&x, &y); // x = 2y 182 | mclBnG2_add(&z, &y, &y); 183 | CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z)); 184 | mclBnG2_add(&z, &z, &y); // z = 3y 185 | mclBnFr n; 186 | mclBnFr_setInt(&n, 3); 187 | mclBnG2_mul(&x, &y, &n); // x = 3y 188 | CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z)); 189 | mclBnG2_sub(&x, &x, &y); // x = 2y 190 | 191 | mclBnFr_setInt(&n, 2); 192 | mclBnG2_mul(&z, &y, &n); // z = 2y 193 | CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z)); 194 | } 195 | 196 | CYBOZU_TEST_AUTO(GT) 197 | { 198 | mclBnGT x, y, z; 199 | memset(&x, 1, sizeof(x)); 200 | CYBOZU_TEST_ASSERT(!mclBnGT_isZero(&x)); 201 | 202 | mclBnGT_clear(&x); 203 | CYBOZU_TEST_ASSERT(mclBnGT_isZero(&x)); 204 | 205 | mclBnGT_setInt(&x, 1); 206 | CYBOZU_TEST_ASSERT(mclBnGT_isOne(&x)); 207 | char buf[2048]; 208 | size_t size; 209 | size = mclBnGT_getStr(buf, sizeof(buf), &x, 10); 210 | CYBOZU_TEST_ASSERT(size > 0); 211 | CYBOZU_TEST_EQUAL(size, strlen(buf)); 212 | const char *s = "1 0 0 0 0 0 0 0 0 0 0 0"; 213 | CYBOZU_TEST_EQUAL(buf, s); 214 | 215 | s = "1 2 3 4 5 6 7 8 9 10 11 12"; 216 | CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&x,s , strlen(s), 10)); 217 | size = mclBnGT_getStr(buf, sizeof(buf), &x, 10); 218 | CYBOZU_TEST_ASSERT(size > 0); 219 | CYBOZU_TEST_EQUAL(size, strlen(buf)); 220 | CYBOZU_TEST_EQUAL(buf, s); 221 | 222 | y = x; 223 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &y)); 224 | 225 | s = "-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12"; 226 | CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&z, s, strlen(s), 10)); 227 | size = mclBnGT_getStr(buf, sizeof(buf), &z, 10); 228 | CYBOZU_TEST_ASSERT(size > 0); 229 | CYBOZU_TEST_EQUAL(size, strlen(buf)); 230 | CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&y, buf, size, 10)); 231 | 232 | mclBnGT_neg(&z, &y); 233 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &z)); 234 | 235 | mclBnGT_add(&y, &x, &y); 236 | CYBOZU_TEST_ASSERT(mclBnGT_isZero(&y)); 237 | 238 | s = "2 0 0 0 0 0 0 0 0 0 0 0"; 239 | CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&y, s, strlen(s), 10)); 240 | mclBnGT_mul(&z, &x, &y); 241 | size = mclBnGT_getStr(buf, sizeof(buf), &z, 10); 242 | CYBOZU_TEST_ASSERT(size > 0); 243 | CYBOZU_TEST_EQUAL(size, strlen(buf)); 244 | CYBOZU_TEST_EQUAL(buf, "2 4 6 8 10 12 14 16 18 20 22 24"); 245 | 246 | mclBnGT_div(&z, &z, &y); 247 | size = mclBnGT_getStr(buf, sizeof(buf), &x, 10); 248 | CYBOZU_TEST_ASSERT(size > 0); 249 | CYBOZU_TEST_EQUAL(size, strlen(buf)); 250 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &z)); 251 | 252 | /* 253 | can't use mclBnGT_pow because x is not in GT 254 | */ 255 | mclBnFr n; 256 | mclBnFr_setInt(&n, 3); 257 | mclBnGT_powGeneric(&z, &x, &n); 258 | mclBnGT_mul(&y, &x, &x); 259 | mclBnGT_mul(&y, &y, &x); 260 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&y, &z)); 261 | } 262 | 263 | CYBOZU_TEST_AUTO(pairing) 264 | { 265 | mclBnFr a, b, ab; 266 | mclBnFr_setInt(&a, 123); 267 | mclBnFr_setInt(&b, 456); 268 | mclBnFr_mul(&ab, &a, &b); 269 | mclBnG1 P, aP; 270 | mclBnG2 Q, bQ; 271 | mclBnGT e, e1, e2; 272 | 273 | CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P, "1", 1)); 274 | CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q, "1", 1)); 275 | 276 | mclBnG1_mul(&aP, &P, &a); 277 | mclBnG2_mul(&bQ, &Q, &b); 278 | 279 | mclBn_pairing(&e, &P, &Q); 280 | mclBnGT_pow(&e1, &e, &a); 281 | mclBn_pairing(&e2, &aP, &Q); 282 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2)); 283 | 284 | mclBnGT_pow(&e1, &e, &b); 285 | mclBn_pairing(&e2, &P, &bQ); 286 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2)); 287 | 288 | mclBnFr n; 289 | mclBnFr_setInt(&n, 3); 290 | mclBnGT_pow(&e1, &e, &n); 291 | mclBnGT_mul(&e2, &e, &e); 292 | mclBnGT_mul(&e2, &e2, &e); 293 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2)); 294 | } 295 | 296 | CYBOZU_TEST_AUTO(precomputed) 297 | { 298 | mclBnG1 P1, P2; 299 | mclBnG2 Q1, Q2; 300 | CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P1, "1", 1)); 301 | CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P2, "123", 3)); 302 | CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q1, "1", 1)); 303 | CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q2, "2", 1)); 304 | 305 | const int size = mclBn_getUint64NumToPrecompute(); 306 | std::vector Q1buf, Q2buf; 307 | Q1buf.resize(size); 308 | Q2buf.resize(size); 309 | mclBn_precomputeG2(Q1buf.data(), &Q1); 310 | mclBn_precomputeG2(Q2buf.data(), &Q2); 311 | 312 | mclBnGT e1, e2, f1, f2, f3; 313 | mclBn_pairing(&e1, &P1, &Q1); 314 | mclBn_precomputedMillerLoop(&f1, &P1, Q1buf.data()); 315 | mclBn_finalExp(&f1, &f1); 316 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &f1)); 317 | 318 | mclBn_pairing(&e2, &P2, &Q2); 319 | mclBn_precomputedMillerLoop(&f2, &P2, Q2buf.data()); 320 | mclBn_finalExp(&f2, &f2); 321 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e2, &f2)); 322 | 323 | mclBn_precomputedMillerLoop2(&f3, &P1, Q1buf.data(), &P2, Q2buf.data()); 324 | mclBn_finalExp(&f3, &f3); 325 | 326 | mclBnGT_mul(&e1, &e1, &e2); 327 | CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &f3)); 328 | } 329 | 330 | CYBOZU_TEST_AUTO(serialize) 331 | { 332 | const size_t opUnitSize = mclBn_getOpUnitSize(); 333 | mclBnFr x1, x2; 334 | mclBnG1 P1, P2; 335 | mclBnG2 Q1, Q2; 336 | char buf[1024]; 337 | size_t n; 338 | size_t expectSize; 339 | int ret; 340 | // Fr 341 | expectSize = opUnitSize * 8; 342 | mclBnFr_setInt(&x1, -1); 343 | n = mclBnFr_serialize(buf, sizeof(buf), &x1); 344 | CYBOZU_TEST_EQUAL(n, expectSize); 345 | 346 | ret = mclBnFr_deserialize(&x2, buf, n); 347 | CYBOZU_TEST_EQUAL(ret, 0); 348 | CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2)); 349 | 350 | ret = mclBnFr_deserialize(&x2, buf, n - 1); 351 | CYBOZU_TEST_ASSERT(ret != 0); 352 | 353 | memset(&x2, 0, sizeof(x2)); 354 | ret = mclBnFr_deserialize(&x2, buf, n + 1); 355 | CYBOZU_TEST_EQUAL(ret, 0); 356 | CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2)); 357 | 358 | n = mclBnFr_serialize(buf, expectSize, &x1); 359 | CYBOZU_TEST_EQUAL(n, expectSize); 360 | 361 | // G1 362 | expectSize = opUnitSize * 8; 363 | mclBnG1_hashAndMapTo(&P1, "1", 1); 364 | n = mclBnG1_serialize(buf, sizeof(buf), &P1); 365 | CYBOZU_TEST_EQUAL(n, expectSize); 366 | 367 | ret = mclBnG1_deserialize(&P2, buf, n); 368 | CYBOZU_TEST_EQUAL(ret, 0); 369 | CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2)); 370 | 371 | ret = mclBnG1_deserialize(&P2, buf, n - 1); 372 | CYBOZU_TEST_ASSERT(ret != 0); 373 | 374 | memset(&P2, 0, sizeof(P2)); 375 | ret = mclBnG1_deserialize(&P2, buf, n + 1); 376 | CYBOZU_TEST_EQUAL(ret, 0); 377 | CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2)); 378 | 379 | n = mclBnG1_serialize(buf, expectSize, &P1); 380 | CYBOZU_TEST_EQUAL(n, expectSize); 381 | 382 | // G2 383 | expectSize = opUnitSize * 8 * 2; 384 | mclBnG2_hashAndMapTo(&Q1, "1", 1); 385 | n = mclBnG2_serialize(buf, sizeof(buf), &Q1); 386 | CYBOZU_TEST_EQUAL(n, expectSize); 387 | 388 | ret = mclBnG2_deserialize(&Q2, buf, n); 389 | CYBOZU_TEST_EQUAL(ret, 0); 390 | CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2)); 391 | 392 | ret = mclBnG2_deserialize(&Q2, buf, n - 1); 393 | CYBOZU_TEST_ASSERT(ret != 0); 394 | 395 | memset(&Q2, 0, sizeof(Q2)); 396 | ret = mclBnG2_deserialize(&Q2, buf, n + 1); 397 | CYBOZU_TEST_EQUAL(ret, 0); 398 | CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2)); 399 | 400 | n = mclBnG2_serialize(buf, expectSize, &Q1); 401 | CYBOZU_TEST_EQUAL(n, expectSize); 402 | } 403 | 404 | #if MCLBN_FP_UNIT_SIZE == 6 405 | CYBOZU_TEST_AUTO(badG2) 406 | { 407 | int ret; 408 | ret = mclBn_init(mclBn_CurveFp382_1, MCLBN_FP_UNIT_SIZE); 409 | CYBOZU_TEST_EQUAL(ret, 0); 410 | const char *s = "1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50"; 411 | mclBnG2 Q; 412 | ret = mclBnG2_setStr(&Q, s, strlen(s), 16); 413 | CYBOZU_TEST_ASSERT(ret != 0); 414 | } 415 | #endif 416 | 417 | CYBOZU_TEST_AUTO(end) 418 | { 419 | int ret = mclBn_setErrFile("bn_if.log"); 420 | CYBOZU_TEST_EQUAL(ret, 0); 421 | } 422 | -------------------------------------------------------------------------------- /mcl/test/bn_test.cpp: -------------------------------------------------------------------------------- 1 | #define PUT(x) std::cout << #x "=" << x << std::endl; 2 | #define CYBOZU_TEST_DISABLE_AUTO_RUN 3 | #include 4 | cybozu::CpuClock clk; 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST) 11 | #define MCL_AVOID_EXCEPTION_TEST 12 | #endif 13 | 14 | typedef mcl::bn256::BN::Compress Compress; 15 | using namespace mcl::bn256; 16 | 17 | mcl::fp::Mode g_mode; 18 | 19 | const struct TestSet { 20 | mcl::bn::CurveParam cp; 21 | const char *name; 22 | struct G2 { 23 | const char *aa; 24 | const char *ab; 25 | const char *ba; 26 | const char *bb; 27 | } g2; 28 | struct G1 { 29 | int a; 30 | int b; 31 | } g1; 32 | const char *e; 33 | } g_testSetTbl[] = { 34 | { 35 | mcl::bn::CurveFp254BNb, 36 | "CurveFp254BNb", 37 | { 38 | "12723517038133731887338407189719511622662176727675373276651903807414909099441", 39 | "4168783608814932154536427934509895782246573715297911553964171371032945126671", 40 | "13891744915211034074451795021214165905772212241412891944830863846330766296736", 41 | "7937318970632701341203597196594272556916396164729705624521405069090520231616", 42 | }, 43 | { 44 | -1, 1 45 | }, 46 | "8118772341496577043438385328606447626730215814727396173233264007541007797690 " 47 | "6742571767760762192519140673058087976840103832045324348366170860928670686713 " 48 | "9727912590495366720378364920530546614235713408261568635512172059018197267630 " 49 | "10180700148605185348549931182990442059136187839792856455707820203302941578832 " 50 | "5054507763444412917986776641611331046146804026682679569910978464879371792565 " 51 | "6917005519826733659554708445125877487590687705432214234949972860245110398023 " 52 | "10448556317747236258066222816126375978842661908560317699736569642190930635294 " 53 | "1516980358051268127904344653343215863076753141133525905743113718749531324025 " 54 | "9794836735385959178744195210089532061310424844916928682580569566332541022353 " 55 | "9375574834170998962484906689780052970915033987453510324648351251071086068423 " 56 | "710778048594563655498360873129325895716179849942646859397874562033386335205 " 57 | "10688745994254573144943003027511098295097561129365638275727908595677791826005" 58 | }, 59 | { 60 | mcl::bn::CurveSNARK1, 61 | "CurveSNARK1", 62 | { 63 | "15267802884793550383558706039165621050290089775961208824303765753922461897946", 64 | "9034493566019742339402378670461897774509967669562610788113215988055021632533", 65 | "644888581738283025171396578091639672120333224302184904896215738366765861164", 66 | "20532875081203448695448744255224543661959516361327385779878476709582931298750", 67 | }, 68 | { 69 | 1, 2 70 | }, 71 | "15163392945550945552839911839294582974434771053565812675833291179413834896953 " 72 | "20389211011850518572149982239826345669421868561029856883955740401696801984953 " 73 | "17766795911013516700216709333389761327222334145011922123798810516425387779347 " 74 | "6064163297423711021549973931984064750876944939004405231004441199168710504090 " 75 | "296093106139306574860102680862436174771023602986903675151017278048818344347 " 76 | "1573596951222456889652521728261836933382094474023551133585236991207205981715 " 77 | "3511871642997169996730611220058787939468653751355351269812083879279936651479 " 78 | "17848534184080172844395614793152774197360421729995967636680357250333093768504 " 79 | "3273860031361637906105800996652640969711942192883181518057117446820546419132 " 80 | "7212721189663231589365009629980400132745687533815732336503876102977912682966 " 81 | "18569236611881855981733896549089319395087993987737891870319625215675547032585 " 82 | "10088832670068482545658647976676953228519838542958787800193793260459700064172 " 83 | }, 84 | }; 85 | 86 | CYBOZU_TEST_AUTO(size) 87 | { 88 | CYBOZU_TEST_EQUAL(sizeof(Fp), 32u); 89 | CYBOZU_TEST_EQUAL(sizeof(Fp2), sizeof(Fp) * 2); 90 | CYBOZU_TEST_EQUAL(sizeof(Fp6), sizeof(Fp) * 6); 91 | CYBOZU_TEST_EQUAL(sizeof(Fp12), sizeof(Fp) * 12); 92 | CYBOZU_TEST_EQUAL(sizeof(G1), sizeof(Fp) * 3); 93 | CYBOZU_TEST_EQUAL(sizeof(G2), sizeof(Fp2) * 3); 94 | } 95 | 96 | void testSetStr(const G2& Q0) 97 | { 98 | G2::setCompressedExpression(); 99 | G2 Q; 100 | Q.clear(); 101 | for (int i = 0; i < 10; i++) { 102 | G2 R; 103 | R.setStr(Q.getStr()); 104 | CYBOZU_TEST_EQUAL(Q, R); 105 | G2::add(Q, Q, Q0); 106 | } 107 | } 108 | 109 | void testMapToG1() 110 | { 111 | G1 g; 112 | for (int i = 1; i < 10; i++) { 113 | BN::mapToG1(g, i); 114 | CYBOZU_TEST_ASSERT(!g.isZero()); 115 | G1 gr; 116 | G1::mul(gr, g, BN::param.r); 117 | CYBOZU_TEST_ASSERT(gr.isZero()); 118 | } 119 | #ifndef MCL_AVOID_EXCEPTION_TEST 120 | if (BN::param.b == 2) { 121 | CYBOZU_TEST_EXCEPTION(BN::mapToG1(g, 0), cybozu::Exception); 122 | CYBOZU_TEST_EXCEPTION(BN::mapToG1(g, BN::param.mapTo.c1), cybozu::Exception); 123 | CYBOZU_TEST_EXCEPTION(BN::mapToG1(g, -BN::param.mapTo.c1), cybozu::Exception); 124 | } 125 | #endif 126 | } 127 | 128 | void testMapToG2() 129 | { 130 | G2 g; 131 | for (int i = 1; i < 10; i++) { 132 | BN::mapToG2(g, i); 133 | CYBOZU_TEST_ASSERT(!g.isZero()); 134 | G2 gr; 135 | G2::mul(gr, g, BN::param.r); 136 | CYBOZU_TEST_ASSERT(gr.isZero()); 137 | } 138 | #ifndef MCL_AVOID_EXCEPTION_TEST 139 | if (BN::param.b == 2) { 140 | CYBOZU_TEST_EXCEPTION(BN::mapToG2(g, 0), cybozu::Exception); 141 | } 142 | #endif 143 | Fp x; 144 | x.setHashOf("abc"); 145 | BN::mapToG2(g, Fp2(x, 0)); 146 | CYBOZU_TEST_ASSERT(g.isValid()); 147 | } 148 | 149 | void testCyclotomic() 150 | { 151 | Fp12 a; 152 | for (int i = 0; i < 12; ++i) { 153 | a.getFp0()[i] = i * i; 154 | } 155 | BN::mapToCyclotomic(a, a); 156 | Fp12 d; 157 | Compress b(d, a); 158 | a *= a; 159 | Fp12 d2; 160 | Compress c(d2, b); 161 | Compress::square_n(c, 1); 162 | c.decompress(); 163 | CYBOZU_TEST_EQUAL(a, d2); 164 | Compress::square_n(b, 1); 165 | b.decompress(); 166 | CYBOZU_TEST_EQUAL(a, d); 167 | } 168 | 169 | void testCompress() 170 | { 171 | if (!BN::param.isCurveFp254BNb) return; 172 | Fp12 a; 173 | for (int i = 0; i < 12; ++i) { 174 | a.getFp0()[i] = i; 175 | } 176 | BN::mapToCyclotomic(a, a); 177 | Fp12 b; 178 | Compress::fixed_power(b, a); 179 | Fp12 c; 180 | Fp12::pow(c, a, BN::param.abs_z); 181 | CYBOZU_TEST_EQUAL(b, c); 182 | } 183 | 184 | void testPrecomputed(const G1& P, const G2& Q) 185 | { 186 | Fp12 e1, e2; 187 | BN::pairing(e1, P, Q); 188 | std::vector Qcoeff; 189 | BN::precomputeG2(Qcoeff, Q); 190 | BN::precomputedMillerLoop(e2, P, Qcoeff); 191 | BN::finalExp(e2, e2); 192 | CYBOZU_TEST_EQUAL(e1, e2); 193 | } 194 | 195 | void testFp12pow(const G1& P, const G2& Q) 196 | { 197 | Fp12 e, e1, e2; 198 | BN::pairing(e, P, Q); 199 | cybozu::XorShift rg; 200 | for (int i = -10; i < 10; i++) { 201 | mpz_class xm = i; 202 | Fp12::pow(e1, e, xm); 203 | Fp12::powGeneric(e2, e, xm); 204 | CYBOZU_TEST_EQUAL(e1, e2); 205 | } 206 | for (int i = 0; i < 10; i++) { 207 | Fr x; 208 | x.setRand(rg); 209 | mpz_class xm = x.getMpz(); 210 | Fp12::pow(e1, e, xm); 211 | BN::param.glv2.pow(e2, e, xm); 212 | CYBOZU_TEST_EQUAL(e1, e2); 213 | } 214 | } 215 | 216 | void testMillerLoop2(const G1& P1, const G2& Q1) 217 | { 218 | Fp12 e1, e2; 219 | mpz_class c1("12342342423442"); 220 | mpz_class c2("329428049820348209482"); 221 | G2 Q2; 222 | G1 P2; 223 | G2::mul(Q2, Q1, c1); 224 | G1::mul(P2, P1, c2); 225 | BN::pairing(e1, P1, Q1); 226 | BN::pairing(e2, P2, Q2); 227 | e1 *= e2; 228 | 229 | std::vector Q1coeff, Q2coeff; 230 | BN::precomputeG2(Q1coeff, Q1); 231 | BN::precomputeG2(Q2coeff, Q2); 232 | BN::precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff); 233 | BN::finalExp(e2, e2); 234 | CYBOZU_TEST_EQUAL(e1, e2); 235 | } 236 | 237 | void testPairing(const G1& P, const G2& Q, const char *eStr) 238 | { 239 | Fp12 e1; 240 | BN::pairing(e1, P, Q); 241 | Fp12 e2; 242 | { 243 | std::stringstream ss(eStr); 244 | ss >> e2; 245 | } 246 | CYBOZU_TEST_EQUAL(e1, e2); 247 | #ifdef ONLY_BENCH 248 | // for (int i = 0; i < 1000; i++) BN::pairing(e1, P, Q); 249 | CYBOZU_BENCH_C("pairing", 1000, BN::pairing, e1, P, Q); // 2.4Mclk 250 | #else 251 | { 252 | Fp12 e = e1, ea; 253 | G1 Pa; 254 | G2 Qa; 255 | #if defined(__EMSCRIPTEN__) || MCL_SIZEOF_UNIT == 4 256 | const int count = 100; 257 | #else 258 | const int count = 1000; 259 | #endif 260 | mpz_class a; 261 | cybozu::XorShift rg; 262 | for (int i = 0; i < count; i++) { 263 | Fr r; 264 | r.setRand(rg); 265 | a = r.getMpz(); 266 | Fp12::pow(ea, e, a); 267 | G1::mul(Pa, P, a); 268 | G2::mul(Qa, Q, a); 269 | G1 T; 270 | G1::mulCT(T, P, a); 271 | CYBOZU_TEST_EQUAL(Pa, T); 272 | BN::pairing(e1, Pa, Q); 273 | BN::pairing(e2, P, Qa); 274 | CYBOZU_TEST_EQUAL(ea, e1); 275 | CYBOZU_TEST_EQUAL(ea, e2); 276 | } 277 | mpz_class z = 3; 278 | CYBOZU_BENCH_C("G1::mulCT ", 500, G1::mulCT, Pa, P, a); 279 | CYBOZU_BENCH_C("G1::mulCT z", 500, G1::mulCT, Pa, P, z); 280 | CYBOZU_BENCH_C("G1::mul ", 500, G1::mul, Pa, Pa, a); 281 | CYBOZU_BENCH_C("G1::mul z", 500, G1::mul, Pa, Pa, z); 282 | CYBOZU_BENCH_C("G1::add", 500, G1::add, Pa, Pa, P); 283 | CYBOZU_BENCH_C("G1::dbl", 500, G1::dbl, Pa, Pa); 284 | CYBOZU_BENCH_C("G2::mulCT ", 500, G2::mulCT, Qa, Q, a); 285 | CYBOZU_BENCH_C("G2::mulCT z", 500, G2::mulCT, Qa, Q, z); 286 | CYBOZU_BENCH_C("G2::mul ", 500, G2::mul, Qa, Qa, a); 287 | CYBOZU_BENCH_C("G2::mul z", 500, G2::mul, Qa, Qa, z); 288 | CYBOZU_BENCH_C("G2::add", 500, G2::add, Qa, Qa, Q); 289 | CYBOZU_BENCH_C("G2::dbl", 500, G2::dbl, Qa, Qa); 290 | CYBOZU_BENCH_C("GT::pow", 500, GT::pow, e1, e1, a); 291 | CYBOZU_BENCH_C("GT::powGLV", 500, BN::param.glv2.pow, e1, e1, a); 292 | G1 PP; 293 | G2 QQ; 294 | CYBOZU_BENCH_C("hashAndMapToG1", 500, BN::hashAndMapToG1, PP, "abc", 3); 295 | CYBOZU_BENCH_C("hashAndMapToG2", 500, BN::hashAndMapToG2, QQ, "abc", 3); 296 | } 297 | CYBOZU_BENCH("pairing", BN::pairing, e1, P, Q); // 2.4Mclk 298 | CYBOZU_BENCH("finalExp", BN::finalExp, e1, e1); // 1.3Mclk 299 | #endif 300 | } 301 | 302 | void testTrivial(const G1& P, const G2& Q) 303 | { 304 | G1 Z1; Z1.clear(); 305 | G2 Z2; Z2.clear(); 306 | Fp12 e; 307 | BN::pairing(e, Z1, Q); 308 | CYBOZU_TEST_EQUAL(e, 1); 309 | BN::pairing(e, P, Z2); 310 | CYBOZU_TEST_EQUAL(e, 1); 311 | BN::pairing(e, Z1, Z2); 312 | CYBOZU_TEST_EQUAL(e, 1); 313 | 314 | std::vector Qcoeff; 315 | BN::precomputeG2(Qcoeff, Z2); 316 | BN::precomputedMillerLoop(e, P, Qcoeff); 317 | BN::finalExp(e, e); 318 | CYBOZU_TEST_EQUAL(e, 1); 319 | 320 | BN::precomputeG2(Qcoeff, Q); 321 | BN::precomputedMillerLoop(e, Z1, Qcoeff); 322 | BN::finalExp(e, e); 323 | CYBOZU_TEST_EQUAL(e, 1); 324 | } 325 | 326 | void testIoAll(const G1& P, const G2& Q) 327 | { 328 | int FpTbl[] = { 0, 2, 2|mcl::IoPrefix, 10, 16, 16|mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw }; 329 | int EcTbl[] = { mcl::IoEcAffine, mcl::IoEcProj, mcl::IoEcCompY, mcl::IoFixedSizeByteSeq }; 330 | for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(FpTbl); i++) { 331 | for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(EcTbl); j++) { 332 | G1 P2 = P, P3; 333 | G2 Q2 = Q, Q3; 334 | int ioMode = FpTbl[i] | EcTbl[j]; 335 | std::string s = P2.getStr(ioMode); 336 | P3.setStr(s, ioMode); 337 | CYBOZU_TEST_EQUAL(P2, P3); 338 | s = Q2.getStr(ioMode); 339 | Q3.setStr(s, ioMode); 340 | CYBOZU_TEST_EQUAL(Q2, Q3); 341 | } 342 | } 343 | } 344 | 345 | void testIo(const G1& P, const G2& Q) 346 | { 347 | testIoAll(P, Q); 348 | G1 Z1; 349 | G2 Z2; 350 | Z1.clear(); 351 | Z2.clear(); 352 | testIoAll(Z1, Z2); 353 | } 354 | 355 | CYBOZU_TEST_AUTO(naive) 356 | { 357 | for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(g_testSetTbl); i++) { 358 | const TestSet& ts = g_testSetTbl[i]; 359 | printf("curve=%s\n", ts.name); 360 | initPairing(ts.cp, g_mode); 361 | G1 P(ts.g1.a, ts.g1.b); 362 | G2 Q(Fp2(ts.g2.aa, ts.g2.ab), Fp2(ts.g2.ba, ts.g2.bb)); 363 | testFp12pow(P, Q); 364 | testIo(P, Q); 365 | testTrivial(P, Q); 366 | testSetStr(Q); 367 | testMapToG1(); 368 | testMapToG2(); 369 | testCyclotomic(); 370 | testCompress(); 371 | testPairing(P, Q, ts.e); 372 | testPrecomputed(P, Q); 373 | testMillerLoop2(P, Q); 374 | testHashAndMapto(); 375 | } 376 | int count = (int)clk.getCount(); 377 | if (count) { 378 | printf("count=%d ", count); 379 | clk.put(); 380 | } 381 | } 382 | 383 | int main(int argc, char *argv[]) 384 | try 385 | { 386 | cybozu::Option opt; 387 | std::string mode; 388 | opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)"); 389 | if (!opt.parse(argc, argv)) { 390 | opt.usage(); 391 | return 1; 392 | } 393 | g_mode = mcl::fp::StrToMode(mode); 394 | printf("JIT %d\n", mcl::fp::isEnableJIT()); 395 | return cybozu::test::autoRun.run(argc, argv); 396 | } catch (std::exception& e) { 397 | printf("ERR %s\n", e.what()); 398 | return 1; 399 | } 400 | -------------------------------------------------------------------------------- /xbyak/xbyak/xbyak_bin2hex.h: -------------------------------------------------------------------------------- 1 | enum { 2 | B00000000= 0, 3 | B00000001= 1, 4 | B00000010= 2, 5 | B00000011= 3, 6 | B00000100= 4, 7 | B00000101= 5, 8 | B00000110= 6, 9 | B00000111= 7, 10 | B00001000= 8, 11 | B00001001= 9, 12 | B00001010= 10, 13 | B00001011= 11, 14 | B00001100= 12, 15 | B00001101= 13, 16 | B00001110= 14, 17 | B00001111= 15, 18 | B00010000= 16, 19 | B00010001= 17, 20 | B00010010= 18, 21 | B00010011= 19, 22 | B00010100= 20, 23 | B00010101= 21, 24 | B00010110= 22, 25 | B00010111= 23, 26 | B00011000= 24, 27 | B00011001= 25, 28 | B00011010= 26, 29 | B00011011= 27, 30 | B00011100= 28, 31 | B00011101= 29, 32 | B00011110= 30, 33 | B00011111= 31, 34 | B00100000= 32, 35 | B00100001= 33, 36 | B00100010= 34, 37 | B00100011= 35, 38 | B00100100= 36, 39 | B00100101= 37, 40 | B00100110= 38, 41 | B00100111= 39, 42 | B00101000= 40, 43 | B00101001= 41, 44 | B00101010= 42, 45 | B00101011= 43, 46 | B00101100= 44, 47 | B00101101= 45, 48 | B00101110= 46, 49 | B00101111= 47, 50 | B00110000= 48, 51 | B00110001= 49, 52 | B00110010= 50, 53 | B00110011= 51, 54 | B00110100= 52, 55 | B00110101= 53, 56 | B00110110= 54, 57 | B00110111= 55, 58 | B00111000= 56, 59 | B00111001= 57, 60 | B00111010= 58, 61 | B00111011= 59, 62 | B00111100= 60, 63 | B00111101= 61, 64 | B00111110= 62, 65 | B00111111= 63, 66 | B01000000= 64, 67 | B01000001= 65, 68 | B01000010= 66, 69 | B01000011= 67, 70 | B01000100= 68, 71 | B01000101= 69, 72 | B01000110= 70, 73 | B01000111= 71, 74 | B01001000= 72, 75 | B01001001= 73, 76 | B01001010= 74, 77 | B01001011= 75, 78 | B01001100= 76, 79 | B01001101= 77, 80 | B01001110= 78, 81 | B01001111= 79, 82 | B01010000= 80, 83 | B01010001= 81, 84 | B01010010= 82, 85 | B01010011= 83, 86 | B01010100= 84, 87 | B01010101= 85, 88 | B01010110= 86, 89 | B01010111= 87, 90 | B01011000= 88, 91 | B01011001= 89, 92 | B01011010= 90, 93 | B01011011= 91, 94 | B01011100= 92, 95 | B01011101= 93, 96 | B01011110= 94, 97 | B01011111= 95, 98 | B01100000= 96, 99 | B01100001= 97, 100 | B01100010= 98, 101 | B01100011= 99, 102 | B01100100= 100, 103 | B01100101= 101, 104 | B01100110= 102, 105 | B01100111= 103, 106 | B01101000= 104, 107 | B01101001= 105, 108 | B01101010= 106, 109 | B01101011= 107, 110 | B01101100= 108, 111 | B01101101= 109, 112 | B01101110= 110, 113 | B01101111= 111, 114 | B01110000= 112, 115 | B01110001= 113, 116 | B01110010= 114, 117 | B01110011= 115, 118 | B01110100= 116, 119 | B01110101= 117, 120 | B01110110= 118, 121 | B01110111= 119, 122 | B01111000= 120, 123 | B01111001= 121, 124 | B01111010= 122, 125 | B01111011= 123, 126 | B01111100= 124, 127 | B01111101= 125, 128 | B01111110= 126, 129 | B01111111= 127, 130 | B10000000= 128, 131 | B10000001= 129, 132 | B10000010= 130, 133 | B10000011= 131, 134 | B10000100= 132, 135 | B10000101= 133, 136 | B10000110= 134, 137 | B10000111= 135, 138 | B10001000= 136, 139 | B10001001= 137, 140 | B10001010= 138, 141 | B10001011= 139, 142 | B10001100= 140, 143 | B10001101= 141, 144 | B10001110= 142, 145 | B10001111= 143, 146 | B10010000= 144, 147 | B10010001= 145, 148 | B10010010= 146, 149 | B10010011= 147, 150 | B10010100= 148, 151 | B10010101= 149, 152 | B10010110= 150, 153 | B10010111= 151, 154 | B10011000= 152, 155 | B10011001= 153, 156 | B10011010= 154, 157 | B10011011= 155, 158 | B10011100= 156, 159 | B10011101= 157, 160 | B10011110= 158, 161 | B10011111= 159, 162 | B10100000= 160, 163 | B10100001= 161, 164 | B10100010= 162, 165 | B10100011= 163, 166 | B10100100= 164, 167 | B10100101= 165, 168 | B10100110= 166, 169 | B10100111= 167, 170 | B10101000= 168, 171 | B10101001= 169, 172 | B10101010= 170, 173 | B10101011= 171, 174 | B10101100= 172, 175 | B10101101= 173, 176 | B10101110= 174, 177 | B10101111= 175, 178 | B10110000= 176, 179 | B10110001= 177, 180 | B10110010= 178, 181 | B10110011= 179, 182 | B10110100= 180, 183 | B10110101= 181, 184 | B10110110= 182, 185 | B10110111= 183, 186 | B10111000= 184, 187 | B10111001= 185, 188 | B10111010= 186, 189 | B10111011= 187, 190 | B10111100= 188, 191 | B10111101= 189, 192 | B10111110= 190, 193 | B10111111= 191, 194 | B11000000= 192, 195 | B11000001= 193, 196 | B11000010= 194, 197 | B11000011= 195, 198 | B11000100= 196, 199 | B11000101= 197, 200 | B11000110= 198, 201 | B11000111= 199, 202 | B11001000= 200, 203 | B11001001= 201, 204 | B11001010= 202, 205 | B11001011= 203, 206 | B11001100= 204, 207 | B11001101= 205, 208 | B11001110= 206, 209 | B11001111= 207, 210 | B11010000= 208, 211 | B11010001= 209, 212 | B11010010= 210, 213 | B11010011= 211, 214 | B11010100= 212, 215 | B11010101= 213, 216 | B11010110= 214, 217 | B11010111= 215, 218 | B11011000= 216, 219 | B11011001= 217, 220 | B11011010= 218, 221 | B11011011= 219, 222 | B11011100= 220, 223 | B11011101= 221, 224 | B11011110= 222, 225 | B11011111= 223, 226 | B11100000= 224, 227 | B11100001= 225, 228 | B11100010= 226, 229 | B11100011= 227, 230 | B11100100= 228, 231 | B11100101= 229, 232 | B11100110= 230, 233 | B11100111= 231, 234 | B11101000= 232, 235 | B11101001= 233, 236 | B11101010= 234, 237 | B11101011= 235, 238 | B11101100= 236, 239 | B11101101= 237, 240 | B11101110= 238, 241 | B11101111= 239, 242 | B11110000= 240, 243 | B11110001= 241, 244 | B11110010= 242, 245 | B11110011= 243, 246 | B11110100= 244, 247 | B11110101= 245, 248 | B11110110= 246, 249 | B11110111= 247, 250 | B11111000= 248, 251 | B11111001= 249, 252 | B11111010= 250, 253 | B11111011= 251, 254 | B11111100= 252, 255 | B11111101= 253, 256 | B11111110= 254, 257 | B11111111= 255 258 | }; 259 | --------------------------------------------------------------------------------