add binding of she for python

pull/2/head
MITSUNARI Shigeo 6 years ago
parent ace9d509ea
commit 9dc5b41fbc
  1. 13
      Makefile
  2. 297
      ffi/python/she.py

@ -45,9 +45,10 @@ BN384_256_SLIB=$(LIB_DIR)/lib$(BN384_256_SNAME).$(LIB_SUF)
BN512_LIB=$(LIB_DIR)/libmclbn512.a
BN512_SLIB=$(LIB_DIR)/lib$(BN512_SNAME).$(LIB_SUF)
SHE256_LIB=$(LIB_DIR)/libmclshe256.a
SHE256_SLIB=$(LIB_DIR)/lib$(SHE256_SNAME).$(LIB_SUF)
SHE384_LIB=$(LIB_DIR)/libmclshe384.a
ECDSA_LIB=$(LIB_DIR)/libmclecdsa.a
all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN384_256_LIB) $(BN384_256_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE256_LIB) $(SHE384_lib) $(ECDSA_LIB)
all: $(MCL_LIB) $(MCL_SLIB) $(BN256_LIB) $(BN256_SLIB) $(BN384_LIB) $(BN384_SLIB) $(BN384_256_LIB) $(BN384_256_SLIB) $(BN512_LIB) $(BN512_SLIB) $(SHE256_LIB) $(SHE256_SLIB) $(SHE384_lib) $(ECDSA_LIB)
#LLVM_VER=-3.8
LLVM_LLC=llc$(LLVM_VER)
@ -121,6 +122,7 @@ ifneq ($(findstring $(OS),mac/mingw64),)
BN384_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
BN384_256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
BN512_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
SHE256_SLIB_LDFLAGS+=-l$(MCL_SNAME) -L./lib
endif
ifeq ($(OS),mingw64)
MCL_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(MCL_SNAME).a
@ -128,6 +130,7 @@ ifeq ($(OS),mingw64)
BN384_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN384_SNAME).a
BN384_256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN384_256_SNAME).a
BN512_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(BN512_SNAME).a
SHE256_SLIB_LDFLAGS+=-Wl,--out-implib,$(LIB_DIR)/lib$(SHE256_SNAME).a
endif
$(MCL_LIB): $(LIB_OBJ)
@ -142,6 +145,9 @@ $(BN256_LIB): $(BN256_OBJ)
$(SHE256_LIB): $(SHE256_OBJ)
$(AR) $@ $(SHE256_OBJ)
$(SHE256_SLIB): $(SHE256_OBJ) $(MCL_LIB)
$(PRE)$(CXX) -o $@ $(SHE256_OBJ) $(MCL_LIB) -shared $(LDFLAGS) $(SHE256_SLIB_LDFLAGS)
$(SHE384_LIB): $(SHE384_OBJ)
$(AR) $@ $(SHE384_OBJ)
@ -224,6 +230,11 @@ test_go:
$(MAKE) test_go384
$(MAKE) test_go384_256
test_python_she: $(SHE256_SLIB)
cd ffi/python && env LD_LIBRARY_PATH="../../lib" DYLD_LIBRARY_PATH="../../lib" PATH=$$PATH:"../../lib" python3 she.py
test_python:
$(MAKE) test_python_she
test_java:
$(MAKE) -C ffi/java test

@ -0,0 +1,297 @@
import os
import platform
from ctypes import *
MCL_BN254 = 0
MCLBN_FR_UNIT_SIZE = 4
MCLBN_FP_UNIT_SIZE = 4
FR_SIZE = MCLBN_FR_UNIT_SIZE
G1_SIZE = MCLBN_FP_UNIT_SIZE * 3
G2_SIZE = MCLBN_FP_UNIT_SIZE * 6
GT_SIZE = MCLBN_FP_UNIT_SIZE * 12
SEC_SIZE = FR_SIZE * 2
PUB_SIZE = G1_SIZE + G2_SIZE
G1_CIPHER_SIZE = G1_SIZE * 2
G2_CIPHER_SIZE = G2_SIZE * 2
GT_CIPHER_SIZE = GT_SIZE * 4
MCLBN_COMPILED_TIME_VAR = (MCLBN_FR_UNIT_SIZE * 10) + MCLBN_FP_UNIT_SIZE
Buffer = c_ubyte * 1536
lib = None
def init(curveType=MCL_BN254):
global lib
name = platform.system()
if name == 'Linux':
suf = 'so'
elif name == 'Darwin':
suf = 'dylib'
else:
raise RuntimeError("not support yet", name)
libname = "libmclshe256." + suf
lib = cdll.LoadLibrary(libname)
ret = lib.sheInit(MCL_BN254, MCLBN_COMPILED_TIME_VAR)
if ret != 0:
raise RuntimeError("sheInit", ret)
# custom setup for a function which returns pointer
lib.shePrecomputedPublicKeyCreate.restype = c_void_p
def setRangeForDLP(hashSize):
ret = lib.sheSetRangeForDLP(hashSize)
if ret != 0:
raise RuntimeError("setRangeForDLP", ret)
def setTryNum(tryNum):
ret = lib.sheSetTryNum(tryNum)
if ret != 0:
raise RuntimeError("setTryNum", ret)
def hexStr(v):
s = ""
for x in v:
s += format(x, '02x')
return s
class CipherTextG1(Structure):
_fields_ = [("v", c_ulonglong * G1_CIPHER_SIZE)]
def serialize(self):
buf = Buffer()
ret = lib.sheCipherTextG1Serialize(byref(buf), len(buf), byref(self.v))
if ret == 0:
raise RuntimeError("serialize")
return buf[0:ret]
def serializeToHexStr(self):
return hexStr(self.serialize())
class CipherTextG2(Structure):
_fields_ = [("v", c_ulonglong * G2_CIPHER_SIZE)]
def serialize(self):
buf = Buffer()
ret = lib.sheCipherTextG2Serialize(byref(buf), len(buf), byref(self.v))
if ret == 0:
raise RuntimeError("serialize")
return buf[0:ret]
def serializeToHexStr(self):
return hexStr(self.serialize())
class CipherTextGT(Structure):
_fields_ = [("v", c_ulonglong * GT_CIPHER_SIZE)]
def serialize(self):
buf = Buffer()
ret = lib.sheCipherTextGTSerialize(byref(buf), len(buf), byref(self.v))
if ret == 0:
raise RuntimeError("serialize")
return buf[0:ret]
def serializeToHexStr(self):
return hexStr(self.serialize())
class PrecomputedPublicKey(Structure):
def __init__(self):
self.p = 0
def create(self):
if not self.p:
self.p = c_void_p(lib.shePrecomputedPublicKeyCreate())
if self.p == 0:
raise RuntimeError("PrecomputedPublicKey::create")
def destroy(self):
lib.shePrecomputedPublicKeyDestroy(self.p)
def encG1(self, m):
c = CipherTextG1()
ret = lib.shePrecomputedPublicKeyEncG1(byref(c.v), self.p, m)
if ret != 0:
raise RuntimeError("encG1", m)
return c
def encG2(self, m):
c = CipherTextG2()
ret = lib.shePrecomputedPublicKeyEncG2(byref(c.v), self.p, m)
if ret != 0:
raise RuntimeError("encG2", m)
return c
def encGT(self, m):
c = CipherTextGT()
ret = lib.shePrecomputedPublicKeyEncGT(byref(c.v), self.p, m)
if ret != 0:
raise RuntimeError("encGT", m)
return c
class PublicKey(Structure):
_fields_ = [("v", c_ulonglong * PUB_SIZE)]
def serialize(self):
buf = Buffer()
ret = lib.shePublicKeySerialize(byref(buf), len(buf), byref(self.v))
if ret == 0:
raise RuntimeError("serialize")
return buf[0:ret]
def serializeToHexStr(self):
return hexStr(self.serialize())
def encG1(self, m):
c = CipherTextG1()
ret = lib.sheEncG1(byref(c.v), byref(self.v), m)
if ret != 0:
raise RuntimeError("encG1", m)
return c
def encG2(self, m):
c = CipherTextG2()
ret = lib.sheEncG2(byref(c.v), byref(self.v), m)
if ret != 0:
raise RuntimeError("encG2", m)
return c
def encGT(self, m):
c = CipherTextGT()
ret = lib.sheEncGT(byref(c.v), byref(self.v), m)
if ret != 0:
raise RuntimeError("encGT", m)
return c
def createPrecomputedPublicKey(self):
ppub = PrecomputedPublicKey()
ppub.create()
ret = lib.shePrecomputedPublicKeyInit(ppub.p, byref(self.v))
if ret != 0:
raise RuntimeError("createPrecomputedPublicKey")
return ppub
class SecretKey(Structure):
_fields_ = [("v", c_ulonglong * SEC_SIZE)]
def setByCSPRNG(self):
ret = lib.sheSecretKeySetByCSPRNG(byref(self.v))
if ret != 0:
raise RuntimeError("setByCSPRNG", ret)
def serialize(self):
buf = Buffer()
ret = lib.sheSecretKeySerialize(byref(buf), len(buf), byref(self.v))
if ret == 0:
raise RuntimeError("serialize")
return buf[0:ret]
def serializeToHexStr(self):
return hexStr(self.serialize())
def getPulicKey(self):
pub = PublicKey()
lib.sheGetPublicKey(byref(pub.v), byref(self.v))
return pub
def dec(self, c):
m = c_longlong()
if isinstance(c, CipherTextG1):
ret = lib.sheDecG1(byref(m), byref(self.v), byref(c.v))
elif isinstance(c, CipherTextG2):
ret = lib.sheDecG2(byref(m), byref(self.v), byref(c.v))
elif isinstance(c, CipherTextGT):
ret = lib.sheDecGT(byref(m), byref(self.v), byref(c.v))
if ret != 0:
raise RuntimeError("dec")
return m.value
def neg(c):
ret = -1
if isinstance(c, CipherTextG1):
out = CipherTextG1()
ret = lib.sheNegG1(byref(out.v), byref(c.v))
elif isinstance(c, CipherTextG2):
out = CipherTextG2()
ret = lib.sheNegG2(byref(out.v), byref(c.v))
elif isinstance(c, CipherTextGT):
out = CipherTextGT()
ret = lib.sheNegGT(byref(out.v), byref(c.v))
if ret != 0:
raise RuntimeError("neg")
return out
def add(cx, cy):
ret = -1
if isinstance(cx, CipherTextG1) and isinstance(cy, CipherTextG1):
out = CipherTextG1()
ret = lib.sheAddG1(byref(out.v), byref(cx.v), byref(cy.v))
elif isinstance(cx, CipherTextG2) and isinstance(cy, CipherTextG2):
out = CipherTextG2()
ret = lib.sheAddG2(byref(out.v), byref(cx.v), byref(cy.v))
elif isinstance(cx, CipherTextGT) and isinstance(cy, CipherTextGT):
out = CipherTextGT()
ret = lib.sheAddGT(byref(out.v), byref(cx.v), byref(cy.v))
if ret != 0:
raise RuntimeError("add")
return out
def sub(cx, cy):
ret = -1
if isinstance(cx, CipherTextG1) and isinstance(cy, CipherTextG1):
out = CipherTextG1()
ret = lib.sheSubG1(byref(out.v), byref(cx.v), byref(cy.v))
elif isinstance(cx, CipherTextG2) and isinstance(cy, CipherTextG2):
out = CipherTextG2()
ret = lib.sheSubG2(byref(out.v), byref(cx.v), byref(cy.v))
elif isinstance(cx, CipherTextGT) and isinstance(cy, CipherTextGT):
out = CipherTextGT()
ret = lib.sheSubGT(byref(out.v), byref(cx.v), byref(cy.v))
if ret != 0:
raise RuntimeError("sub")
return out
def mul(cx, cy):
ret = -1
if isinstance(cx, CipherTextG1) and isinstance(cy, CipherTextG2):
out = CipherTextGT()
ret = lib.sheMul(byref(out.v), byref(cx.v), byref(cy.v))
elif isinstance(cx, CipherTextG1) and isinstance(cy, int):
out = CipherTextG1()
ret = lib.sheMulG1(byref(out.v), byref(cx.v), cy)
elif isinstance(cx, CipherTextG2) and isinstance(cy, int):
out = CipherTextG2()
ret = lib.sheMulG2(byref(out.v), byref(cx.v), cy)
elif isinstance(cx, CipherTextGT) and isinstance(cy, int):
out = CipherTextGT()
ret = lib.sheMulGT(byref(out.v), byref(cx.v), cy)
if ret != 0:
raise RuntimeError("mul")
return out
if __name__ == '__main__':
init()
sec = SecretKey()
sec.setByCSPRNG()
print("sec=", sec.serializeToHexStr())
pub = sec.getPulicKey()
print("pub=", pub.serializeToHexStr())
m11 = 1
m12 = 5
m21 = 3
m22 = -4
c11 = pub.encG1(m11)
c12 = pub.encG1(m12)
# dec(enc) for G1
if sec.dec(c11) != m11: print("err1")
# add/sub for G1
if sec.dec(add(c11, c12)) != m11 + m12: print("err2")
if sec.dec(sub(c11, c12)) != m11 - m12: print("err3")
# add/sub for G2
c21 = pub.encG2(m21)
c22 = pub.encG2(m22)
if sec.dec(c21) != m21: print("err4")
if sec.dec(add(c21, c22)) != m21 + m22: print("err5")
if sec.dec(sub(c21, c22)) != m21 - m22: print("err6")
mt = -56
ct = pub.encGT(mt)
if sec.dec(ct) != mt: print("err7")
# mul G1 and G2
if sec.dec(mul(c11, c21)) != m11 * m21: print("err8")
# use precomputedPublicKey for performance
ppub = pub.createPrecomputedPublicKey()
c1 = ppub.encG1(m11)
if sec.dec(c1) != m11: print("err9")
import sys
if sys.version_info.major >= 3:
import timeit
N = 100000
print(str(timeit.timeit("pub.encG1(12)", number=N, globals=globals()) / float(N) * 1e3) + "msec")
print(str(timeit.timeit("ppub.encG1(12)", number=N, globals=globals()) / float(N) * 1e3) + "msec")
ppub.destroy() # necessary to avoid memory leak
Loading…
Cancel
Save