aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <herumi@nifty.com>2017-09-28 16:56:19 +0800
committerMITSUNARI Shigeo <herumi@nifty.com>2017-09-28 16:56:19 +0800
commit3bd6edfca63031c3e872143de932602cd00bb385 (patch)
tree4323593b457238f19ae45a542135b32da3df32c0
parente2c7097f797805e1364849610342e1b6f38ab083 (diff)
downloaddexon-mcl-3bd6edfca63031c3e872143de932602cd00bb385.tar.gz
dexon-mcl-3bd6edfca63031c3e872143de932602cd00bb385.tar.zst
dexon-mcl-3bd6edfca63031c3e872143de932602cd00bb385.zip
[she] add C api for she
-rw-r--r--Makefile15
-rw-r--r--include/mcl/she.h139
-rw-r--r--mklib.bat5
-rw-r--r--src/she_c256.cpp2
-rw-r--r--src/she_c_impl.hpp364
-rw-r--r--test/she_c256_test.cpp2
-rw-r--r--test/she_c_test.hpp184
7 files changed, 708 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 51a1196..f4d52e1 100644
--- a/Makefile
+++ b/Makefile
@@ -2,9 +2,9 @@ include common.mk
LIB_DIR=lib
OBJ_DIR=obj
EXE_DIR=bin
-SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp
+SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp she_c256.cpp
TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp
-TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp
+TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp she_c256_test.cpp
ifeq ($(CPU),x86-64)
MCL_USE_XBYAK?=1
TEST_SRC+=mont_fp_test.cpp sq_test.cpp
@@ -29,12 +29,14 @@ MCL_LIB=$(LIB_DIR)/libmcl.a
MCL_SNAME=mcl$(SHARE_BASENAME_SUF)
BN256_SNAME=mclbn256$(SHARE_BASENAME_SUF)
BN384_SNAME=mclbn384$(SHARE_BASENAME_SUF)
+SHE256_SNAME=mclshe256$(SHARE_BASENAME_SUF)
MCL_SLIB=$(LIB_DIR)/lib$(MCL_SNAME).$(LIB_SUF)
BN256_LIB=$(LIB_DIR)/libmclbn256.a
BN256_SLIB=$(LIB_DIR)/lib$(BN256_SNAME).$(LIB_SUF)
BN384_LIB=$(LIB_DIR)/libmclbn384.a
BN384_SLIB=$(LIB_DIR)/lib$(BN384_SNAME).$(LIB_SUF)
-all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB)
+SHE256_LIB=$(LIB_DIR)/libmclshe256.a
+all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(SHE256_LIB)
#LLVM_VER=-3.8
LLVM_LLC=llc$(LLVM_VER)
@@ -57,6 +59,7 @@ ASM_OBJ=$(OBJ_DIR)/$(CPU).o
LIB_OBJ=$(OBJ_DIR)/fp.o
BN256_OBJ=$(OBJ_DIR)/bn_c256.o
BN384_OBJ=$(OBJ_DIR)/bn_c384.o
+SHE256_OBJ=$(OBJ_DIR)/she_c256.o
FUNC_LIST=src/func.list
MCL_USE_LLVM?=1
ifeq ($(MCL_USE_LLVM),1)
@@ -101,6 +104,9 @@ $(MCL_SLIB): $(LIB_OBJ)
$(BN256_LIB): $(BN256_OBJ)
$(AR) $@ $(BN256_OBJ)
+$(SHE256_LIB): $(SHE256_OBJ)
+ $(AR) $@ $(SHE256_OBJ)
+
ifeq ($(OS),mac)
MAC_LDFLAGS+=-l$(MCL_SNAME) -L./lib
endif
@@ -185,6 +191,9 @@ $(EXE_DIR)/bn_c384_test.exe: $(OBJ_DIR)/bn_c384_test.o $(BN384_LIB) $(MCL_LIB)
$(EXE_DIR)/pairing_c.exe: $(OBJ_DIR)/pairing_c.o $(BN256_LIB) $(MCL_LIB)
$(PRE)$(CC) $< -o $@ $(BN256_LIB) $(MCL_LIB) $(LDFLAGS) -lstdc++
+$(EXE_DIR)/she_c256_test.exe: $(OBJ_DIR)/she_c256_test.o $(SHE256_LIB) $(MCL_LIB)
+ $(PRE)$(CXX) $< -o $@ $(SHE256_LIB) $(MCL_LIB) $(LDFLAGS)
+
SAMPLE_EXE=$(addprefix $(EXE_DIR)/,$(addsuffix .exe,$(basename $(SAMPLE_SRC))))
sample: $(SAMPLE_EXE) $(MCL_LIB)
diff --git a/include/mcl/she.h b/include/mcl/she.h
new file mode 100644
index 0000000..3d13962
--- /dev/null
+++ b/include/mcl/she.h
@@ -0,0 +1,139 @@
+#pragma once
+/**
+ @file
+ @brief C api of somewhat homomorphic encryption with one-time multiplication, based on prime-order pairings
+ @author MITSUNARI Shigeo(@herumi)
+ @license modified new BSD license
+ http://opensource.org/licenses/BSD-3-Clause
+*/
+#include <mcl/bn.h>
+
+#ifdef _MSC_VER
+#ifdef MCLSHE_DLL_EXPORT
+#define MCLSHE_DLL_API __declspec(dllexport)
+#else
+#define MCLSHE_DLL_API __declspec(dllimport)
+#ifndef MCLSHE_NO_AUTOLINK
+ #if MCLBN_FP_UNIT_SIZE == 4
+ #pragma comment(lib, "mclshe256.lib")
+ #elif MCLBN_FP_UNIT_SIZE == 6
+ #pragma comment(lib, "mclshe384.lib")
+ #else
+ #pragma comment(lib, "mclshe512.lib")
+ #endif
+#endif
+#endif
+#else
+#define MCLSHE_DLL_API
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ mclBnFr x;
+ mclBnFr y;
+} sheSecretKey;
+
+typedef struct {
+ mclBnG1 xP;
+ mclBnG2 yQ;
+} shePublicKey;
+
+typedef struct {
+ mclBnG1 S;
+ mclBnG1 T;
+} sheCipherTextG1;
+
+typedef struct {
+ mclBnG2 S;
+ mclBnG2 T;
+} sheCipherTextG2;
+
+typedef struct {
+ mclBnGT g[4];
+} sheCipherTextGT;
+
+/*
+ initialize this library
+ call this once before using the other functions
+ @param curve [in] enum value defined in mcl/bn.h
+ @param maxUnitSize [in] MCLBN_FP_UNIT_SIZE (fixed)
+ return 0 if success
+ @note sheInit() is thread safe and serialized if it is called simultaneously
+ but don't call it while using other functions.
+*/
+MCLSHE_DLL_API int sheInit(int curve, int maxUnitSize);
+
+// return written byte size if success else 0
+MCLSHE_DLL_API size_t sheSecretKeySerialize(void *buf, size_t maxBufSize, const sheSecretKey *sec);
+MCLSHE_DLL_API size_t shePublicKeySerialize(void *buf, size_t maxBufSize, const shePublicKey *pub);
+MCLSHE_DLL_API size_t sheCipherTextG1Serialize(void *buf, size_t maxBufSize, const sheCipherTextG1 *c);
+MCLSHE_DLL_API size_t sheCipherTextG2Serialize(void *buf, size_t maxBufSize, const sheCipherTextG2 *c);
+MCLSHE_DLL_API size_t sheCipherTextGTSerialize(void *buf, size_t maxBufSize, const sheCipherTextGT *c);
+
+// return 0 if success else -1
+MCLSHE_DLL_API int sheSecretKeyDeserialize(sheSecretKey* sec, const void *buf, size_t bufSize);
+MCLSHE_DLL_API int shePublicKeyDeserialize(shePublicKey* pub, const void *buf, size_t bufSize);
+MCLSHE_DLL_API int sheCipherTextG1Deserialize(sheCipherTextG1* c, const void *buf, size_t bufSize);
+MCLSHE_DLL_API int sheCipherTextG2Deserialize(sheCipherTextG2* c, const void *buf, size_t bufSize);
+MCLSHE_DLL_API int sheCipherTextGTDeserialize(sheCipherTextGT* c, const void *buf, size_t bufSize);
+
+/*
+ set secretKey if system has /dev/urandom or CryptGenRandom
+ return 0 if success else -1
+*/
+MCLSHE_DLL_API int sheSecretKeySetByCSPRNG(sheSecretKey *sec);
+
+MCLSHE_DLL_API void sheGetPublicKey(shePublicKey *pub, const sheSecretKey *sec);
+
+/*
+ make table to decode DLP
+ return 0 if success else -1
+*/
+MCLSHE_DLL_API int sheSetRangeForDLP(size_t hashSize, size_t tryNum);
+
+// return 0 if success else -1
+MCLSHE_DLL_API int sheEncG1(sheCipherTextG1 *c, const shePublicKey *pub, int64_t m);
+MCLSHE_DLL_API int sheEncG2(sheCipherTextG2 *c, const shePublicKey *pub, int64_t m);
+MCLSHE_DLL_API int sheEncGT(sheCipherTextGT *c, const shePublicKey *pub, int64_t m);
+
+#define MCLSHE_ERR_DECODE 0x7fffffffffffffffll
+
+// return MCLSHE_ERR_DECODE if error
+MCLSHE_DLL_API int64_t sheDecG1(const sheSecretKey *sec, const sheCipherTextG1 *c);
+//MCLSHE_DLL_API int64_t sheDecG2(const sheSecretKey *sec, const sheCipherTextG2 *c);
+MCLSHE_DLL_API int64_t sheDecGT(const sheSecretKey *sec, const sheCipherTextGT *c);
+
+// return 0 if success
+// z = x + y
+MCLSHE_DLL_API int sheAddG1(sheCipherTextG1 *z, const sheCipherTextG1 *x, const sheCipherTextG1 *y);
+MCLSHE_DLL_API int sheAddG2(sheCipherTextG2 *z, const sheCipherTextG2 *x, const sheCipherTextG2 *y);
+MCLSHE_DLL_API int sheAddGT(sheCipherTextGT *z, const sheCipherTextGT *x, const sheCipherTextGT *y);
+
+// return 0 if success
+// z = x - y
+MCLSHE_DLL_API int sheSubG1(sheCipherTextG1 *z, const sheCipherTextG1 *x, const sheCipherTextG1 *y);
+MCLSHE_DLL_API int sheSubG2(sheCipherTextG2 *z, const sheCipherTextG2 *x, const sheCipherTextG2 *y);
+MCLSHE_DLL_API int sheSubGT(sheCipherTextGT *z, const sheCipherTextGT *x, const sheCipherTextGT *y);
+
+// return 0 if success
+// z = x * y
+MCLSHE_DLL_API int sheMulG1(sheCipherTextG1 *z, const sheCipherTextG1 *x, int64_t y);
+MCLSHE_DLL_API int sheMulG2(sheCipherTextG2 *z, const sheCipherTextG2 *x, int64_t y);
+MCLSHE_DLL_API int sheMulGT(sheCipherTextGT *z, const sheCipherTextGT *x, int64_t y);
+
+// return 0 if success
+// z = x * y
+MCLSHE_DLL_API int sheMul(sheCipherTextGT *z, const sheCipherTextG1 *x, const sheCipherTextG2 *y);
+
+// return 0 if success
+// rerandomize(c)
+MCLSHE_DLL_API int sheReRandG1(sheCipherTextG1 *c, const shePublicKey *pub);
+MCLSHE_DLL_API int sheReRandG2(sheCipherTextG2 *c, const shePublicKey *pub);
+MCLSHE_DLL_API int sheReRandGT(sheCipherTextGT *c, const shePublicKey *pub);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/mklib.bat b/mklib.bat
index ece2333..ac1b17d 100644
--- a/mklib.bat
+++ b/mklib.bat
@@ -17,3 +17,8 @@ echo cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj
cl /c %CFLAGS% src\bn_c384.cpp /Foobj\bn_c384.obj
echo link /nologo /DLL /OUT:bin\mclbn384.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.lib
link /nologo /DLL /OUT:bin\mclbn384.dll obj\bn_c384.obj obj\fp.obj %LDFLAGS% /implib:lib\mclbn384.lib
+
+echo cl /c %CFLAGS% src\she_c256.cpp /Foobj\she_c256.obj
+ cl /c %CFLAGS% src\she_c256.cpp /Foobj\she_c256.obj
+echo link /nologo /DLL /OUT:bin\mclbn256.dll obj\she_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe256.lib
+ link /nologo /DLL /OUT:bin\mclbn256.dll obj\she_c256.obj obj\fp.obj %LDFLAGS% /implib:lib\mclshe256.lib
diff --git a/src/she_c256.cpp b/src/she_c256.cpp
new file mode 100644
index 0000000..84873e4
--- /dev/null
+++ b/src/she_c256.cpp
@@ -0,0 +1,2 @@
+#define MCLBN_FP_UNIT_SIZE 4
+#include "she_c_impl.hpp"
diff --git a/src/she_c_impl.hpp b/src/she_c_impl.hpp
new file mode 100644
index 0000000..85d2e86
--- /dev/null
+++ b/src/she_c_impl.hpp
@@ -0,0 +1,364 @@
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <string>
+#include <iosfwd>
+#include <stdint.h>
+#include <memory.h>
+#include "../mcl/src/bn_c_impl.hpp"
+#define MCLSHE_DLL_EXPORT
+
+#include <mcl/she.h>
+#include <mcl/she.hpp>
+
+using namespace mcl::she;
+using namespace mcl::bn_current;
+
+#if defined(CYBOZU_CPP_VERSION) && CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11
+#include <mutex>
+ #define USE_STD_MUTEX
+#else
+#include <cybozu/mutex.hpp>
+#endif
+
+static SecretKey *cast(sheSecretKey *p) { return reinterpret_cast<SecretKey*>(p); }
+static const SecretKey *cast(const sheSecretKey *p) { return reinterpret_cast<const SecretKey*>(p); }
+
+static PublicKey *cast(shePublicKey *p) { return reinterpret_cast<PublicKey*>(p); }
+static const PublicKey *cast(const shePublicKey *p) { return reinterpret_cast<const PublicKey*>(p); }
+
+static CipherTextG1 *cast(sheCipherTextG1 *p) { return reinterpret_cast<CipherTextG1*>(p); }
+static const CipherTextG1 *cast(const sheCipherTextG1 *p) { return reinterpret_cast<const CipherTextG1*>(p); }
+
+static CipherTextG2 *cast(sheCipherTextG2 *p) { return reinterpret_cast<CipherTextG2*>(p); }
+static const CipherTextG2 *cast(const sheCipherTextG2 *p) { return reinterpret_cast<const CipherTextG2*>(p); }
+
+static CipherTextGT *cast(sheCipherTextGT *p) { return reinterpret_cast<CipherTextGT*>(p); }
+static const CipherTextGT *cast(const sheCipherTextGT *p) { return reinterpret_cast<const CipherTextGT*>(p); }
+
+int sheInit(int curve, int maxUnitSize)
+ try
+{
+ if (maxUnitSize != MCLBN_FP_UNIT_SIZE) {
+ printf("err sheInit:maxUnitSize is mismatch %d %d\n", maxUnitSize, MCLBN_FP_UNIT_SIZE);
+ return -1;
+ }
+#ifdef USE_STD_MUTEX
+ static std::mutex m;
+ std::lock_guard<std::mutex> lock(m);
+#else
+ static cybozu::Mutex m;
+ cybozu::AutoLock lock(m);
+#endif
+ static int g_curve = -1;
+ if (g_curve == curve) return 0;
+
+ mcl::bn::CurveParam cp;
+ switch (curve) {
+ case mclBn_CurveFp254BNb:
+ cp = mcl::bn::CurveFp254BNb;
+ break;
+ case mclBn_CurveFp382_1:
+ cp = mcl::bn::CurveFp382_1;
+ break;
+ case mclBn_CurveFp382_2:
+ cp = mcl::bn::CurveFp382_2;
+ break;
+ case mclBn_CurveFp462:
+ cp = mcl::bn::CurveFp462;
+ break;
+ default:
+ printf("err bad curve %d\n", curve);
+ return -1;
+ }
+ SHE::init(cp);
+ g_curve = curve;
+ return 0;
+} catch (std::exception& e) {
+ printf("err sheInit %s\n", e.what());
+ return -1;
+}
+
+size_t sheSecretKeySerialize(void *buf, size_t maxBufSize, const sheSecretKey *sec)
+{
+ char *p = (char *)buf;
+ size_t n = mclBnFr_serialize(p, maxBufSize, &sec->x);
+ if (n == 0) return 0;
+ return n += mclBnFr_serialize(p + n, maxBufSize - n, &sec->y);
+}
+
+size_t shePublicKeySerialize(void *buf, size_t maxBufSize, const shePublicKey *pub)
+{
+ char *p = (char *)buf;
+ size_t n = mclBnG1_serialize(p, maxBufSize, &pub->xP);
+ if (n == 0) return 0;
+ return n += mclBnG2_serialize(p + n, maxBufSize - n, &pub->yQ);
+}
+
+size_t sheCipherTextG1Serialize(void *buf, size_t maxBufSize, const sheCipherTextG1 *c)
+{
+ char *p = (char *)buf;
+ size_t n = mclBnG1_serialize(p, maxBufSize, &c->S);
+ if (n == 0) return 0;
+ return n += mclBnG1_serialize(p + n, maxBufSize - n, &c->T);
+}
+
+size_t sheCipherTextG2Serialize(void *buf, size_t maxBufSize, const sheCipherTextG2 *c)
+{
+ char *p = (char *)buf;
+ size_t n = mclBnG2_serialize(p, maxBufSize, &c->S);
+ if (n == 0) return 0;
+ return n += mclBnG2_serialize(p + n, maxBufSize - n, &c->T);
+}
+
+size_t sheCipherTextGTSerialize(void *buf, size_t maxBufSize, const sheCipherTextGT *c)
+{
+ char *p = (char *)buf;
+ size_t n = 0;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(c->g); i++) {
+ size_t r = mclBnGT_serialize(p + n, maxBufSize - n, &c->g[i]);
+ if (r == 0) return 0;
+ n += r;
+ }
+ return n;
+}
+
+int sheSecretKeyDeserialize(sheSecretKey* sec, const void *buf, size_t bufSize)
+{
+ const char *p = (const char *)buf;
+ if (mclBnFr_deserialize(&sec->x, p, bufSize)) return -1;
+ const size_t size = Fr::getByteSize();
+ return mclBnFr_deserialize(&sec->y, p + size, bufSize - size);
+}
+
+int shePublicKeyDeserialize(shePublicKey* sec, const void *buf, size_t bufSize)
+{
+ const char *p = (const char *)buf;
+ if (mclBnG1_deserialize(&sec->xP, p, bufSize)) return -1;
+ const size_t size = Fr::getByteSize();
+ return mclBnG2_deserialize(&sec->yQ, p + size, bufSize - size);
+}
+
+int sheCipherTextG1Deserialize(sheCipherTextG1* c, const void *buf, size_t bufSize)
+{
+ const char *p = (const char *)buf;
+ if (mclBnG1_deserialize(&c->S, p, bufSize)) return -1;
+ const size_t size = Fr::getByteSize();
+ return mclBnG1_deserialize(&c->T, p + size, bufSize - size);
+}
+
+int sheCipherTextG2Deserialize(sheCipherTextG2* c, const void *buf, size_t bufSize)
+{
+ const char *p = (const char *)buf;
+ if (mclBnG2_deserialize(&c->S, p, bufSize)) return -1;
+ const size_t size = Fr::getByteSize() * 2;
+ return mclBnG2_deserialize(&c->T, p + size, bufSize - size);
+}
+
+int sheCipherTextGTDeserialize(sheCipherTextGT* c, const void *buf, size_t bufSize)
+{
+ const char *p = (const char *)buf;
+ const size_t size = Fr::getByteSize() * 12;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(c->g); i++) {
+ if (mclBnGT_deserialize(&c->g[i], p + size * i, bufSize - size * i)) return -1;
+ }
+ return 0;
+}
+
+int sheSecretKeySetByCSPRNG(sheSecretKey *sec)
+ try
+{
+ cast(sec)->setByCSPRNG();
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+void sheGetPublicKey(shePublicKey *pub, const sheSecretKey *sec)
+{
+ cast(sec)->getPublicKey(*cast(pub));
+}
+
+int sheSetRangeForDLP(size_t hashSize, size_t tryNum)
+ try
+{
+ SHE::setRangeForDLP(hashSize, tryNum);
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheEncG1(sheCipherTextG1 *c, const shePublicKey *pub, int64_t m)
+ try
+{
+ cast(pub)->enc(*cast(c), m);
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheEncG2(sheCipherTextG2 *c, const shePublicKey *pub, int64_t m)
+ try
+{
+ cast(pub)->enc(*cast(c), m);
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheEncGT(sheCipherTextGT *c, const shePublicKey *pub, int64_t m)
+ try
+{
+ cast(pub)->enc(*cast(c), m);
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int64_t sheDecG1(const sheSecretKey *sec, const sheCipherTextG1 *c)
+ try
+{
+ return cast(sec)->dec(*cast(c));
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return MCLSHE_ERR_DECODE;
+}
+
+int64_t sheDecGT(const sheSecretKey *sec, const sheCipherTextGT *c)
+ try
+{
+ return cast(sec)->dec(*cast(c));
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return MCLSHE_ERR_DECODE;
+}
+
+int sheAddG1(sheCipherTextG1 *z, const sheCipherTextG1 *x, const sheCipherTextG1 *y)
+ try
+{
+ CipherTextG1::add(*cast(z), *cast(x), *cast(y));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheAddG2(sheCipherTextG2 *z, const sheCipherTextG2 *x, const sheCipherTextG2 *y)
+ try
+{
+ CipherTextG2::add(*cast(z), *cast(x), *cast(y));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+int sheAddGT(sheCipherTextGT *z, const sheCipherTextGT *x, const sheCipherTextGT *y)
+ try
+{
+ CipherTextGT::add(*cast(z), *cast(x), *cast(y));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheSubG1(sheCipherTextG1 *z, const sheCipherTextG1 *x, const sheCipherTextG1 *y)
+ try
+{
+ CipherTextG1::sub(*cast(z), *cast(x), *cast(y));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheSubG2(sheCipherTextG2 *z, const sheCipherTextG2 *x, const sheCipherTextG2 *y)
+ try
+{
+ CipherTextG2::sub(*cast(z), *cast(x), *cast(y));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+int sheSubGT(sheCipherTextGT *z, const sheCipherTextGT *x, const sheCipherTextGT *y)
+ try
+{
+ CipherTextGT::sub(*cast(z), *cast(x), *cast(y));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheMulG1(sheCipherTextG1 *z, const sheCipherTextG1 *x, int64_t y)
+ try
+{
+ CipherTextG1::mul(*cast(z), *cast(x), y);
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheMulG2(sheCipherTextG2 *z, const sheCipherTextG2 *x, int64_t y)
+ try
+{
+ CipherTextG2::mul(*cast(z), *cast(x), y);
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+int sheMulGT(sheCipherTextGT *z, const sheCipherTextGT *x, int64_t y)
+ try
+{
+ CipherTextGT::mul(*cast(z), *cast(x), y);
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheMul(sheCipherTextGT *z, const sheCipherTextG1 *x, const sheCipherTextG2 *y)
+ try
+{
+ CipherTextGT::mul(*cast(z), *cast(x), *cast(y));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+
+int sheReRandG1(sheCipherTextG1 *c, const shePublicKey *pub)
+ try
+{
+ cast(pub)->reRand(*cast(c));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+int sheReRandG2(sheCipherTextG2 *c, const shePublicKey *pub)
+ try
+{
+ cast(pub)->reRand(*cast(c));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
+int sheReRandGT(sheCipherTextGT *c, const shePublicKey *pub)
+ try
+{
+ cast(pub)->reRand(*cast(c));
+ return 0;
+} catch (std::exception& e) {
+ printf("err %s\n", e.what());
+ return -1;
+}
diff --git a/test/she_c256_test.cpp b/test/she_c256_test.cpp
new file mode 100644
index 0000000..3e458b6
--- /dev/null
+++ b/test/she_c256_test.cpp
@@ -0,0 +1,2 @@
+#define MCLBN_FP_UNIT_SIZE 4
+#include "she_c_test.hpp"
diff --git a/test/she_c_test.hpp b/test/she_c_test.hpp
new file mode 100644
index 0000000..1dd2165
--- /dev/null
+++ b/test/she_c_test.hpp
@@ -0,0 +1,184 @@
+#include <mcl/she.h>
+#include <cybozu/test.hpp>
+
+const size_t hashSize = 1 << 10;
+const size_t tryNum = 1024;
+
+CYBOZU_TEST_AUTO(init)
+{
+ int curve;
+#if MCLBN_FP_UNIT_SIZE == 4
+ curve = mclBn_CurveFp254BNb;
+#elif MCLBN_FP_UNIT_SIZE == 6
+ curve = mclBn_CurveFp382_1;
+#elif MCLBN_FP_UNIT_SIZE == 8
+ curve = mclBn_CurveFp462;
+#endif
+ int ret;
+ ret = sheInit(curve, MCLBN_FP_UNIT_SIZE);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ ret = sheSetRangeForDLP(hashSize, tryNum);
+ CYBOZU_TEST_ASSERT(ret == 0);
+}
+
+CYBOZU_TEST_AUTO(encDec)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m = 123;
+ sheCipherTextG1 c1;
+ sheCipherTextGT ct;
+ sheEncG1(&c1, &pub, m);
+ sheEncGT(&ct, &pub, m);
+
+ CYBOZU_TEST_EQUAL(sheDecG1(&sec, &c1), m);
+ CYBOZU_TEST_EQUAL(sheDecGT(&sec, &ct), m);
+}
+
+CYBOZU_TEST_AUTO(addMul)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m1 = 12;
+ int64_t m2 = -9;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct;
+ sheEncG1(&c1, &pub, m1);
+ sheEncG2(&c2, &pub, m2);
+ sheMul(&ct, &c1, &c2);
+
+ CYBOZU_TEST_EQUAL(sheDecGT(&sec, &ct), m1 * m2);
+}
+
+CYBOZU_TEST_AUTO(allOp)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m1 = 12;
+ int64_t m2 = -9;
+ int64_t m3 = 12;
+ int64_t m4 = -9;
+ sheCipherTextG1 c11, c12;
+ sheCipherTextG2 c21, c22;
+ sheCipherTextGT ct;
+ sheEncG1(&c11, &pub, m1);
+ sheEncG1(&c12, &pub, m2);
+ sheSubG1(&c11, &c11, &c12); // m1 - m2
+ sheMulG1(&c11, &c11, 4); // 4 * (m1 - m2)
+
+ sheEncG2(&c21, &pub, m3);
+ sheEncG2(&c22, &pub, m4);
+ sheSubG2(&c21, &c21, &c22); // m3 - m4
+ sheMulG2(&c21, &c21, -5); // -5 * (m3 - m4)
+ sheMul(&ct, &c11, &c21); // -20 * (m1 - m2) * (m3 - m4)
+ sheAddGT(&ct, &ct, &ct); // -40 * (m1 - m2) * (m3 - m4)
+ sheMulGT(&ct, &ct, -4); // 160 * (m1 - m2) * (m3 - m4)
+
+ int64_t t = 160 * (m1 - m2) * (m3 - m4);
+ CYBOZU_TEST_EQUAL(sheDecGT(&sec, &ct), t);
+}
+
+CYBOZU_TEST_AUTO(rerand)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m1 = 12;
+ int64_t m2 = -9;
+ int64_t m3 = 12;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct1, ct2;
+ sheEncG1(&c1, &pub, m1);
+ sheReRandG1(&c1, &pub);
+
+ sheEncG2(&c2, &pub, m2);
+ sheReRandG2(&c2, &pub);
+
+ sheEncGT(&ct1, &pub, m3);
+ sheReRandGT(&ct1, &pub);
+
+ sheMul(&ct2, &c1, &c2);
+ sheReRandGT(&ct2, &pub);
+ sheAddGT(&ct1, &ct1, &ct2);
+
+ CYBOZU_TEST_EQUAL(sheDecGT(&sec, &ct1), m1 * m2 + m3);
+}
+
+CYBOZU_TEST_AUTO(serialize)
+{
+ sheSecretKey sec1, sec2;
+ sheSecretKeySetByCSPRNG(&sec1);
+ shePublicKey pub1, pub2;
+ sheGetPublicKey(&pub1, &sec1);
+
+ char buf1[2048], buf2[2048];
+ size_t n1, n2;
+ size_t r, size;
+ const size_t sizeofFr = mclBn_getOpUnitSize() * 8;
+
+ size = sizeofFr * 2;
+ n1 = sheSecretKeySerialize(buf1, sizeof(buf1), &sec1);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheSecretKeyDeserialize(&sec2, buf1, n1);
+ CYBOZU_TEST_ASSERT(r == 0);
+ n2 = sheSecretKeySerialize(buf2, sizeof(buf2), &sec2);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ size = sizeofFr * 3;
+ n1 = shePublicKeySerialize(buf1, sizeof(buf1), &pub1);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = shePublicKeyDeserialize(&pub2, buf1, n1);
+ CYBOZU_TEST_ASSERT(r == 0);
+ n2 = shePublicKeySerialize(buf2, sizeof(buf2), &pub2);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ int m = 123;
+ sheCipherTextG1 c11, c12;
+ sheCipherTextG2 c21, c22;
+ sheCipherTextGT ct1, ct2;
+ sheEncG1(&c11, &pub2, m);
+ sheEncG2(&c21, &pub2, m);
+ sheEncGT(&ct1, &pub2, m);
+
+ size = sizeofFr * 2;
+ n1 = sheCipherTextG1Serialize(buf1, sizeof(buf1), &c11);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheCipherTextG1Deserialize(&c12, buf1, n1);
+ CYBOZU_TEST_ASSERT(r == 0);
+ n2 = sheCipherTextG1Serialize(buf2, sizeof(buf2), &c12);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ size = sizeofFr * 4;
+ n1 = sheCipherTextG2Serialize(buf1, sizeof(buf1), &c21);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheCipherTextG2Deserialize(&c22, buf1, n1);
+ CYBOZU_TEST_ASSERT(r == 0);
+ n2 = sheCipherTextG2Serialize(buf2, sizeof(buf2), &c22);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ size = sizeofFr * 12 * 4;
+ n1 = sheCipherTextGTSerialize(buf1, sizeof(buf1), &ct1);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheCipherTextGTDeserialize(&ct2, buf1, n1);
+ CYBOZU_TEST_ASSERT(r == 0);
+ n2 = sheCipherTextGTSerialize(buf2, sizeof(buf2), &ct2);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+}