From 8fbb047d8064ae09776db62edaa7dc4ece8ce38d Mon Sep 17 00:00:00 2001 From: MITSUNARI Shigeo Date: Tue, 8 May 2018 11:24:57 +0900 Subject: mov go to ffi/go --- ffi/go/bls/bls.go | 296 +++++++++++++++++++++++ ffi/go/bls/bls_test.go | 520 ++++++++++++++++++++++++++++++++++++++++ ffi/go/bls/mcl.go | 629 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1445 insertions(+) create mode 100644 ffi/go/bls/bls.go create mode 100644 ffi/go/bls/bls_test.go create mode 100644 ffi/go/bls/mcl.go (limited to 'ffi/go') diff --git a/ffi/go/bls/bls.go b/ffi/go/bls/bls.go new file mode 100644 index 0000000..61a96f5 --- /dev/null +++ b/ffi/go/bls/bls.go @@ -0,0 +1,296 @@ +package bls + +/* +#cgo CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 +#cgo LDFLAGS:-lbls384_dy -lgmpxx -lstdc++ -lgmp -lcrypto +#include +*/ +import "C" +import "fmt" +import "unsafe" + +// Init -- +// call this function before calling all the other operations +// this function is not thread safe +func Init(curve int) error { + err := C.blsInit(C.int(curve), C.MCLBN_FP_UNIT_SIZE) + if err != 0 { + return fmt.Errorf("ERR Init curve=%d", curve) + } + return nil +} + +// ID -- +type ID struct { + v Fr +} + +// getPointer -- +func (id *ID) getPointer() (p *C.blsId) { + // #nosec + return (*C.blsId)(unsafe.Pointer(id)) +} + +// GetLittleEndian -- +func (id *ID) GetLittleEndian() []byte { + return id.v.Serialize() +} + +// SetLittleEndian -- +func (id *ID) SetLittleEndian(buf []byte) error { + return id.v.SetLittleEndian(buf) +} + +// GetHexString -- +func (id *ID) GetHexString() string { + return id.v.GetString(16) +} + +// GetDecString -- +func (id *ID) GetDecString() string { + return id.v.GetString(10) +} + +// SetHexString -- +func (id *ID) SetHexString(s string) error { + return id.v.SetString(s, 16) +} + +// SetDecString -- +func (id *ID) SetDecString(s string) error { + return id.v.SetString(s, 10) +} + +// IsEqual -- +func (id *ID) IsEqual(rhs *ID) bool { + return id.v.IsEqual(&rhs.v) +} + +// SecretKey -- +type SecretKey struct { + v Fr +} + +// getPointer -- +func (sec *SecretKey) getPointer() (p *C.blsSecretKey) { + // #nosec + return (*C.blsSecretKey)(unsafe.Pointer(sec)) +} + +// GetLittleEndian -- +func (sec *SecretKey) GetLittleEndian() []byte { + return sec.v.Serialize() +} + +// SetLittleEndian -- +func (sec *SecretKey) SetLittleEndian(buf []byte) error { + return sec.v.SetLittleEndian(buf) +} + +// GetHexString -- +func (sec *SecretKey) GetHexString() string { + return sec.v.GetString(16) +} + +// GetDecString -- +func (sec *SecretKey) GetDecString() string { + return sec.v.GetString(10) +} + +// SetHexString -- +func (sec *SecretKey) SetHexString(s string) error { + return sec.v.SetString(s, 16) +} + +// SetDecString -- +func (sec *SecretKey) SetDecString(s string) error { + return sec.v.SetString(s, 10) +} + +// IsEqual -- +func (sec *SecretKey) IsEqual(rhs *SecretKey) bool { + return sec.v.IsEqual(&rhs.v) +} + +// SetByCSPRNG -- +func (sec *SecretKey) SetByCSPRNG() { + sec.v.SetByCSPRNG() +} + +// Add -- +func (sec *SecretKey) Add(rhs *SecretKey) { + FrAdd(&sec.v, &sec.v, &rhs.v) +} + +// GetMasterSecretKey -- +func (sec *SecretKey) GetMasterSecretKey(k int) (msk []SecretKey) { + msk = make([]SecretKey, k) + msk[0] = *sec + for i := 1; i < k; i++ { + msk[i].SetByCSPRNG() + } + return msk +} + +// GetMasterPublicKey -- +func GetMasterPublicKey(msk []SecretKey) (mpk []PublicKey) { + n := len(msk) + mpk = make([]PublicKey, n) + for i := 0; i < n; i++ { + mpk[i] = *msk[i].GetPublicKey() + } + return mpk +} + +// Set -- +func (sec *SecretKey) Set(msk []SecretKey, id *ID) error { + // #nosec + return FrEvaluatePolynomial(&sec.v, *(*[]Fr)(unsafe.Pointer(&msk)), &id.v) +} + +// Recover -- +func (sec *SecretKey) Recover(secVec []SecretKey, idVec []ID) error { + // #nosec + return FrLagrangeInterpolation(&sec.v, *(*[]Fr)(unsafe.Pointer(&idVec)), *(*[]Fr)(unsafe.Pointer(&secVec))) +} + +// GetPop -- +func (sec *SecretKey) GetPop() (sign *Sign) { + sign = new(Sign) + C.blsGetPop(sign.getPointer(), sec.getPointer()) + return sign +} + +// PublicKey -- +type PublicKey struct { + v G2 +} + +// getPointer -- +func (pub *PublicKey) getPointer() (p *C.blsPublicKey) { + // #nosec + return (*C.blsPublicKey)(unsafe.Pointer(pub)) +} + +// Serialize -- +func (pub *PublicKey) Serialize() []byte { + return pub.v.Serialize() +} + +// Deserialize -- +func (pub *PublicKey) Deserialize(buf []byte) error { + return pub.v.Deserialize(buf) +} + +// GetHexString -- +func (pub *PublicKey) GetHexString() string { + return pub.v.GetString(16) +} + +// SetHexString -- +func (pub *PublicKey) SetHexString(s string) error { + return pub.v.SetString(s, 16) +} + +// IsEqual -- +func (pub *PublicKey) IsEqual(rhs *PublicKey) bool { + return pub.v.IsEqual(&rhs.v) +} + +// Add -- +func (pub *PublicKey) Add(rhs *PublicKey) { + G2Add(&pub.v, &pub.v, &rhs.v) +} + +// Set -- +func (pub *PublicKey) Set(mpk []PublicKey, id *ID) error { + // #nosec + return G2EvaluatePolynomial(&pub.v, *(*[]G2)(unsafe.Pointer(&mpk)), &id.v) +} + +// Recover -- +func (pub *PublicKey) Recover(pubVec []PublicKey, idVec []ID) error { + // #nosec + return G2LagrangeInterpolation(&pub.v, *(*[]Fr)(unsafe.Pointer(&idVec)), *(*[]G2)(unsafe.Pointer(&pubVec))) +} + +// Sign -- +type Sign struct { + v G1 +} + +// getPointer -- +func (sign *Sign) getPointer() (p *C.blsSignature) { + // #nosec + return (*C.blsSignature)(unsafe.Pointer(sign)) +} + +// Serialize -- +func (sign *Sign) Serialize() []byte { + return sign.v.Serialize() +} + +// Deserialize -- +func (sign *Sign) Deserialize(buf []byte) error { + return sign.v.Deserialize(buf) +} + +// GetHexString -- +func (sign *Sign) GetHexString() string { + return sign.v.GetString(16) +} + +// SetHexString -- +func (sign *Sign) SetHexString(s string) error { + return sign.v.SetString(s, 16) +} + +// IsEqual -- +func (sign *Sign) IsEqual(rhs *Sign) bool { + return sign.v.IsEqual(&rhs.v) +} + +// GetPublicKey -- +func (sec *SecretKey) GetPublicKey() (pub *PublicKey) { + pub = new(PublicKey) + C.blsGetPublicKey(pub.getPointer(), sec.getPointer()) + return pub +} + +// Sign -- Constant Time version +func (sec *SecretKey) Sign(m string) (sign *Sign) { + sign = new(Sign) + buf := []byte(m) + // #nosec + C.blsSign(sign.getPointer(), sec.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + return sign +} + +// Add -- +func (sign *Sign) Add(rhs *Sign) { + C.blsSignatureAdd(sign.getPointer(), rhs.getPointer()) +} + +// Recover -- +func (sign *Sign) Recover(signVec []Sign, idVec []ID) error { + // #nosec + return G1LagrangeInterpolation(&sign.v, *(*[]Fr)(unsafe.Pointer(&idVec)), *(*[]G1)(unsafe.Pointer(&signVec))) +} + +// Verify -- +func (sign *Sign) Verify(pub *PublicKey, m string) bool { + buf := []byte(m) + // #nosec + return C.blsVerify(sign.getPointer(), pub.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) == 1 +} + +// VerifyPop -- +func (sign *Sign) VerifyPop(pub *PublicKey) bool { + return C.blsVerifyPop(sign.getPointer(), pub.getPointer()) == 1 +} + +// DHKeyExchange -- +func DHKeyExchange(sec *SecretKey, pub *PublicKey) (out PublicKey) { + C.blsDHKeyExchange(out.getPointer(), sec.getPointer(), pub.getPointer()) + return out +} diff --git a/ffi/go/bls/bls_test.go b/ffi/go/bls/bls_test.go new file mode 100644 index 0000000..400f90d --- /dev/null +++ b/ffi/go/bls/bls_test.go @@ -0,0 +1,520 @@ +package bls + +import "testing" +import "strconv" + +var unitN = 0 + +// Tests (for Benchmarks see below) + +func testPre(t *testing.T) { + t.Log("init") + { + var id ID + err := id.SetLittleEndian([]byte{6, 5, 4, 3, 2, 1}) + if err != nil { + t.Error(err) + } + t.Log("id :", id.GetHexString()) + var id2 ID + err = id2.SetHexString(id.GetHexString()) + if err != nil { + t.Fatal(err) + } + if !id.IsEqual(&id2) { + t.Errorf("not same id\n%s\n%s", id.GetHexString(), id2.GetHexString()) + } + err = id2.SetDecString(id.GetDecString()) + if err != nil { + t.Fatal(err) + } + if !id.IsEqual(&id2) { + t.Errorf("not same id\n%s\n%s", id.GetDecString(), id2.GetDecString()) + } + } + { + var sec SecretKey + err := sec.SetLittleEndian([]byte{1, 2, 3, 4, 5, 6}) + if err != nil { + t.Error(err) + } + t.Log("sec=", sec.GetHexString()) + } + + t.Log("create secret key") + m := "this is a bls sample for go" + var sec SecretKey + sec.SetByCSPRNG() + t.Log("sec:", sec.GetHexString()) + t.Log("create public key") + pub := sec.GetPublicKey() + t.Log("pub:", pub.GetHexString()) + sign := sec.Sign(m) + t.Log("sign:", sign.GetHexString()) + if !sign.Verify(pub, m) { + t.Error("Signature does not verify") + } + + // How to make array of SecretKey + { + sec := make([]SecretKey, 3) + for i := 0; i < len(sec); i++ { + sec[i].SetByCSPRNG() + t.Log("sec=", sec[i].GetHexString()) + } + } +} + +func testStringConversion(t *testing.T) { + t.Log("testRecoverSecretKey") + var sec SecretKey + var s string + if unitN == 6 { + s = "16798108731015832284940804142231733909759579603404752749028378864165570215949" + } else { + s = "40804142231733909759579603404752749028378864165570215949" + } + err := sec.SetDecString(s) + if err != nil { + t.Fatal(err) + } + if s != sec.GetDecString() { + t.Error("not equal") + } + s = sec.GetHexString() + var sec2 SecretKey + err = sec2.SetHexString(s) + if err != nil { + t.Fatal(err) + } + if !sec.IsEqual(&sec2) { + t.Error("not equal") + } +} + +func testRecoverSecretKey(t *testing.T) { + t.Log("testRecoverSecretKey") + k := 3000 + var sec SecretKey + sec.SetByCSPRNG() + t.Logf("sec=%s\n", sec.GetHexString()) + + // make master secret key + msk := sec.GetMasterSecretKey(k) + + n := k + secVec := make([]SecretKey, n) + idVec := make([]ID, n) + for i := 0; i < n; i++ { + err := idVec[i].SetLittleEndian([]byte{byte(i & 255), byte(i >> 8), 2, 3, 4, 5}) + if err != nil { + t.Error(err) + } + err = secVec[i].Set(msk, &idVec[i]) + if err != nil { + t.Error(err) + } + // t.Logf("idVec[%d]=%s\n", i, idVec[i].GetHexString()) + } + // recover sec2 from secVec and idVec + var sec2 SecretKey + err := sec2.Recover(secVec, idVec) + if err != nil { + t.Error(err) + } + if !sec.IsEqual(&sec2) { + t.Errorf("Mismatch in recovered secret key:\n %s\n %s.", sec.GetHexString(), sec2.GetHexString()) + } +} + +func testEachSign(t *testing.T, m string, msk []SecretKey, mpk []PublicKey) ([]ID, []SecretKey, []PublicKey, []Sign) { + idTbl := []byte{3, 5, 193, 22, 15} + n := len(idTbl) + + secVec := make([]SecretKey, n) + pubVec := make([]PublicKey, n) + signVec := make([]Sign, n) + idVec := make([]ID, n) + + for i := 0; i < n; i++ { + err := idVec[i].SetLittleEndian([]byte{idTbl[i], 0, 0, 0, 0, 0}) + if err != nil { + t.Error(err) + } + t.Logf("idVec[%d]=%s\n", i, idVec[i].GetHexString()) + + err = secVec[i].Set(msk, &idVec[i]) + if err != nil { + t.Error(err) + } + + err = pubVec[i].Set(mpk, &idVec[i]) + if err != nil { + t.Error(err) + } + t.Logf("pubVec[%d]=%s\n", i, pubVec[i].GetHexString()) + + if !pubVec[i].IsEqual(secVec[i].GetPublicKey()) { + t.Errorf("Pubkey derivation does not match\n%s\n%s", pubVec[i].GetHexString(), secVec[i].GetPublicKey().GetHexString()) + } + + signVec[i] = *secVec[i].Sign(m) + if !signVec[i].Verify(&pubVec[i], m) { + t.Error("Pubkey derivation does not match") + } + } + return idVec, secVec, pubVec, signVec +} +func testSign(t *testing.T) { + m := "testSign" + t.Log(m) + + var sec0 SecretKey + sec0.SetByCSPRNG() + pub0 := sec0.GetPublicKey() + s0 := sec0.Sign(m) + if !s0.Verify(pub0, m) { + t.Error("Signature does not verify") + } + + k := 3 + msk := sec0.GetMasterSecretKey(k) + mpk := GetMasterPublicKey(msk) + idVec, secVec, pubVec, signVec := testEachSign(t, m, msk, mpk) + + var sec1 SecretKey + err := sec1.Recover(secVec, idVec) + if err != nil { + t.Error(err) + } + if !sec0.IsEqual(&sec1) { + t.Error("Mismatch in recovered seckey.") + } + var pub1 PublicKey + err = pub1.Recover(pubVec, idVec) + if err != nil { + t.Error(err) + } + if !pub0.IsEqual(&pub1) { + t.Error("Mismatch in recovered pubkey.") + } + var s1 Sign + err = s1.Recover(signVec, idVec) + if err != nil { + t.Error(err) + } + if !s0.IsEqual(&s1) { + t.Error("Mismatch in recovered signature.") + } +} + +func testAdd(t *testing.T) { + t.Log("testAdd") + var sec1 SecretKey + var sec2 SecretKey + sec1.SetByCSPRNG() + sec2.SetByCSPRNG() + + pub1 := sec1.GetPublicKey() + pub2 := sec2.GetPublicKey() + + m := "test test" + sign1 := sec1.Sign(m) + sign2 := sec2.Sign(m) + + t.Log("sign1 :", sign1.GetHexString()) + sign1.Add(sign2) + t.Log("sign1 add:", sign1.GetHexString()) + pub1.Add(pub2) + if !sign1.Verify(pub1, m) { + t.Fail() + } +} + +func testPop(t *testing.T) { + t.Log("testPop") + var sec SecretKey + sec.SetByCSPRNG() + pop := sec.GetPop() + if !pop.VerifyPop(sec.GetPublicKey()) { + t.Errorf("Valid Pop does not verify") + } + sec.SetByCSPRNG() + if pop.VerifyPop(sec.GetPublicKey()) { + t.Errorf("Invalid Pop verifies") + } +} + +func testData(t *testing.T) { + t.Log("testData") + var sec1, sec2 SecretKey + sec1.SetByCSPRNG() + b := sec1.GetLittleEndian() + err := sec2.SetLittleEndian(b) + if err != nil { + t.Fatal(err) + } + if !sec1.IsEqual(&sec2) { + t.Error("SecretKey not same") + } + pub1 := sec1.GetPublicKey() + b = pub1.Serialize() + var pub2 PublicKey + err = pub2.Deserialize(b) + if err != nil { + t.Fatal(err) + } + if !pub1.IsEqual(&pub2) { + t.Error("PublicKey not same") + } + m := "doremi" + sign1 := sec1.Sign(m) + b = sign1.Serialize() + var sign2 Sign + err = sign2.Deserialize(b) + if err != nil { + t.Fatal(err) + } + if !sign1.IsEqual(&sign2) { + t.Error("Sign not same") + } +} + +func testOrder(t *testing.T, c int) { + var curve string + var field string + if c == CurveFp254BNb { + curve = "16798108731015832284940804142231733909759579603404752749028378864165570215949" + field = "16798108731015832284940804142231733909889187121439069848933715426072753864723" + } else if c == CurveFp382_1 { + curve = "5540996953667913971058039301942914304734176495422447785042938606876043190415948413757785063597439175372845535461389" + field = "5540996953667913971058039301942914304734176495422447785045292539108217242186829586959562222833658991069414454984723" + } else if c == CurveFp382_2 { + curve = "5541245505022739011583672869577435255026888277144126952448297309161979278754528049907713682488818304329661351460877" + field = "5541245505022739011583672869577435255026888277144126952450651294188487038640194767986566260919128250811286032482323" + } else if c == BLS12_381 { + curve = "52435875175126190479447740508185965837690552500527637822603658699938581184513" + field = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787" + } else { + t.Fatal("bad c", c) + } + s := GetCurveOrder() + if s != curve { + t.Errorf("bad curve order\n%s\n%s\n", s, curve) + } + s = GetFieldOrder() + if s != field { + t.Errorf("bad field order\n%s\n%s\n", s, field) + } +} + +func testDHKeyExchange(t *testing.T) { + var sec1, sec2 SecretKey + sec1.SetByCSPRNG() + sec2.SetByCSPRNG() + pub1 := sec1.GetPublicKey() + pub2 := sec2.GetPublicKey() + out1 := DHKeyExchange(&sec1, pub2) + out2 := DHKeyExchange(&sec2, pub1) + if !out1.IsEqual(&out2) { + t.Errorf("DH key is not equal") + } +} + +func test(t *testing.T, c int) { + err := Init(c) + if err != nil { + t.Fatal(err) + } + unitN = GetOpUnitSize() + t.Logf("unitN=%d\n", unitN) + testPre(t) + testRecoverSecretKey(t) + testAdd(t) + testSign(t) + testPop(t) + testData(t) + testStringConversion(t) + testOrder(t, c) + testDHKeyExchange(t) +} + +func TestMain(t *testing.T) { + t.Logf("GetMaxOpUnitSize() = %d\n", GetMaxOpUnitSize()) + t.Log("CurveFp254BNb") + test(t, CurveFp254BNb) + if GetMaxOpUnitSize() == 6 { + t.Log("CurveFp382_1") + test(t, CurveFp382_1) + t.Log("BLS12_381") + test(t, BLS12_381) + } +} + +// Benchmarks + +var curve = CurveFp382_1 + +//var curve = CurveFp254BNb + +func BenchmarkPubkeyFromSeckey(b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + for n := 0; n < b.N; n++ { + sec.SetByCSPRNG() + b.StartTimer() + sec.GetPublicKey() + b.StopTimer() + } +} + +func BenchmarkSigning(b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + for n := 0; n < b.N; n++ { + sec.SetByCSPRNG() + b.StartTimer() + sec.Sign(strconv.Itoa(n)) + b.StopTimer() + } +} + +func BenchmarkValidation(b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + for n := 0; n < b.N; n++ { + sec.SetByCSPRNG() + pub := sec.GetPublicKey() + m := strconv.Itoa(n) + sig := sec.Sign(m) + b.StartTimer() + sig.Verify(pub, m) + b.StopTimer() + } +} + +func benchmarkDeriveSeckeyShare(k int, b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + sec.SetByCSPRNG() + msk := sec.GetMasterSecretKey(k) + var id ID + for n := 0; n < b.N; n++ { + err = id.SetLittleEndian([]byte{1, 2, 3, 4, 5, byte(n)}) + if err != nil { + b.Error(err) + } + b.StartTimer() + err := sec.Set(msk, &id) + b.StopTimer() + if err != nil { + b.Error(err) + } + } +} + +//func BenchmarkDeriveSeckeyShare100(b *testing.B) { benchmarkDeriveSeckeyShare(100, b) } +//func BenchmarkDeriveSeckeyShare200(b *testing.B) { benchmarkDeriveSeckeyShare(200, b) } +func BenchmarkDeriveSeckeyShare500(b *testing.B) { benchmarkDeriveSeckeyShare(500, b) } + +//func BenchmarkDeriveSeckeyShare1000(b *testing.B) { benchmarkDeriveSeckeyShare(1000, b) } + +func benchmarkRecoverSeckey(k int, b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + sec.SetByCSPRNG() + msk := sec.GetMasterSecretKey(k) + + // derive n shares + n := k + secVec := make([]SecretKey, n) + idVec := make([]ID, n) + for i := 0; i < n; i++ { + err := idVec[i].SetLittleEndian([]byte{1, 2, 3, 4, 5, byte(i)}) + if err != nil { + b.Error(err) + } + err = secVec[i].Set(msk, &idVec[i]) + if err != nil { + b.Error(err) + } + } + + // recover from secVec and idVec + var sec2 SecretKey + b.StartTimer() + for n := 0; n < b.N; n++ { + err := sec2.Recover(secVec, idVec) + if err != nil { + b.Errorf("%s\n", err) + } + } +} + +func BenchmarkRecoverSeckey100(b *testing.B) { benchmarkRecoverSeckey(100, b) } +func BenchmarkRecoverSeckey200(b *testing.B) { benchmarkRecoverSeckey(200, b) } +func BenchmarkRecoverSeckey500(b *testing.B) { benchmarkRecoverSeckey(500, b) } +func BenchmarkRecoverSeckey1000(b *testing.B) { benchmarkRecoverSeckey(1000, b) } + +func benchmarkRecoverSignature(k int, b *testing.B) { + b.StopTimer() + err := Init(curve) + if err != nil { + b.Fatal(err) + } + var sec SecretKey + sec.SetByCSPRNG() + msk := sec.GetMasterSecretKey(k) + + // derive n shares + n := k + idVec := make([]ID, n) + secVec := make([]SecretKey, n) + signVec := make([]Sign, n) + for i := 0; i < n; i++ { + err := idVec[i].SetLittleEndian([]byte{1, 2, 3, 4, 5, byte(i)}) + if err != nil { + b.Error(err) + } + err = secVec[i].Set(msk, &idVec[i]) + if err != nil { + b.Error(err) + } + signVec[i] = *secVec[i].Sign("test message") + } + + // recover signature + var sig Sign + b.StartTimer() + for n := 0; n < b.N; n++ { + err := sig.Recover(signVec, idVec) + if err != nil { + b.Error(err) + } + } +} + +func BenchmarkRecoverSignature100(b *testing.B) { benchmarkRecoverSignature(100, b) } +func BenchmarkRecoverSignature200(b *testing.B) { benchmarkRecoverSignature(200, b) } +func BenchmarkRecoverSignature500(b *testing.B) { benchmarkRecoverSignature(500, b) } +func BenchmarkRecoverSignature1000(b *testing.B) { benchmarkRecoverSignature(1000, b) } diff --git a/ffi/go/bls/mcl.go b/ffi/go/bls/mcl.go new file mode 100644 index 0000000..00feebc --- /dev/null +++ b/ffi/go/bls/mcl.go @@ -0,0 +1,629 @@ +package bls + +/* +#cgo CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 +#include +*/ +import "C" +import "fmt" +import "unsafe" + +// CurveFp254BNb -- 254 bit curve +const CurveFp254BNb = C.mclBn_CurveFp254BNb + +// CurveFp382_1 -- 382 bit curve 1 +const CurveFp382_1 = C.mclBn_CurveFp382_1 + +// CurveFp382_2 -- 382 bit curve 2 +const CurveFp382_2 = C.mclBn_CurveFp382_2 + +// BLS12_381 +const BLS12_381 = C.MCL_BLS12_381 + +// GetMaxOpUnitSize -- +func GetMaxOpUnitSize() int { + return int(C.MCLBN_FP_UNIT_SIZE) +} + +// GetOpUnitSize -- +// the length of Fr is GetOpUnitSize() * 8 bytes +func GetOpUnitSize() int { + return int(C.mclBn_getOpUnitSize()) +} + +// GetCurveOrder -- +// return the order of G1 +func GetCurveOrder() string { + buf := make([]byte, 1024) + // #nosec + n := C.mclBn_getCurveOrder((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))) + if n == 0 { + panic("implementation err. size of buf is small") + } + return string(buf[:n]) +} + +// GetFieldOrder -- +// return the characteristic of the field where a curve is defined +func GetFieldOrder() string { + buf := make([]byte, 1024) + // #nosec + n := C.mclBn_getFieldOrder((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))) + if n == 0 { + panic("implementation err. size of buf is small") + } + return string(buf[:n]) +} + +// Fr -- +type Fr struct { + v C.mclBnFr +} + +// getPointer -- +func (x *Fr) getPointer() (p *C.mclBnFr) { + // #nosec + return (*C.mclBnFr)(unsafe.Pointer(x)) +} + +// Clear -- +func (x *Fr) Clear() { + // #nosec + C.mclBnFr_clear(x.getPointer()) +} + +// SetInt64 -- +func (x *Fr) SetInt64(v int64) { + // #nosec + C.mclBnFr_setInt(x.getPointer(), C.int64_t(v)) +} + +// SetString -- +func (x *Fr) SetString(s string, base int) error { + buf := []byte(s) + // #nosec + err := C.mclBnFr_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) + if err != 0 { + return fmt.Errorf("err mclBnFr_setStr %x", err) + } + return nil +} + +// Deserialize -- +func (x *Fr) Deserialize(buf []byte) error { + // #nosec + err := C.mclBnFr_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err == 0 { + return fmt.Errorf("err mclBnFr_deserialize %x", buf) + } + return nil +} + +// SetLittleEndian -- +func (x *Fr) SetLittleEndian(buf []byte) error { + // #nosec + err := C.mclBnFr_setLittleEndian(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err != 0 { + return fmt.Errorf("err mclBnFr_setLittleEndian %x", err) + } + return nil +} + +// IsEqual -- +func (x *Fr) IsEqual(rhs *Fr) bool { + return C.mclBnFr_isEqual(x.getPointer(), rhs.getPointer()) == 1 +} + +// IsZero -- +func (x *Fr) IsZero() bool { + return C.mclBnFr_isZero(x.getPointer()) == 1 +} + +// IsOne -- +func (x *Fr) IsOne() bool { + return C.mclBnFr_isOne(x.getPointer()) == 1 +} + +// SetByCSPRNG -- +func (x *Fr) SetByCSPRNG() { + err := C.mclBnFr_setByCSPRNG(x.getPointer()) + if err != 0 { + panic("err mclBnFr_setByCSPRNG") + } +} + +// SetHashOf -- +func (x *Fr) SetHashOf(buf []byte) bool { + // #nosec + return C.mclBnFr_setHashOf(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) == 1 +} + +// GetString -- +func (x *Fr) GetString(base int) string { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnFr_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) + if n == 0 { + panic("err mclBnFr_getStr") + } + return string(buf[:n]) +} + +// Serialize -- +func (x *Fr) Serialize() []byte { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnFr_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) + if n == 0 { + panic("err mclBnFr_serialize") + } + return buf[:n] +} + +// FrNeg -- +func FrNeg(out *Fr, x *Fr) { + C.mclBnFr_neg(out.getPointer(), x.getPointer()) +} + +// FrInv -- +func FrInv(out *Fr, x *Fr) { + C.mclBnFr_inv(out.getPointer(), x.getPointer()) +} + +// FrAdd -- +func FrAdd(out *Fr, x *Fr, y *Fr) { + C.mclBnFr_add(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// FrSub -- +func FrSub(out *Fr, x *Fr, y *Fr) { + C.mclBnFr_sub(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// FrMul -- +func FrMul(out *Fr, x *Fr, y *Fr) { + C.mclBnFr_mul(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// FrDiv -- +func FrDiv(out *Fr, x *Fr, y *Fr) { + C.mclBnFr_div(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G1 -- +type G1 struct { + v C.mclBnG1 +} + +// getPointer -- +func (x *G1) getPointer() (p *C.mclBnG1) { + // #nosec + return (*C.mclBnG1)(unsafe.Pointer(x)) +} + +// Clear -- +func (x *G1) Clear() { + // #nosec + C.mclBnG1_clear(x.getPointer()) +} + +// SetString -- +func (x *G1) SetString(s string, base int) error { + buf := []byte(s) + // #nosec + err := C.mclBnG1_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) + if err != 0 { + return fmt.Errorf("err mclBnG1_setStr %x", err) + } + return nil +} + +// Deserialize -- +func (x *G1) Deserialize(buf []byte) error { + // #nosec + err := C.mclBnG1_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err == 0 { + return fmt.Errorf("err mclBnG1_deserialize %x", buf) + } + return nil +} + +// IsEqual -- +func (x *G1) IsEqual(rhs *G1) bool { + return C.mclBnG1_isEqual(x.getPointer(), rhs.getPointer()) == 1 +} + +// IsZero -- +func (x *G1) IsZero() bool { + return C.mclBnG1_isZero(x.getPointer()) == 1 +} + +// HashAndMapTo -- +func (x *G1) HashAndMapTo(buf []byte) error { + // #nosec + err := C.mclBnG1_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err != 0 { + return fmt.Errorf("err mclBnG1_hashAndMapTo %x", err) + } + return nil +} + +// GetString -- +func (x *G1) GetString(base int) string { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnG1_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) + if n == 0 { + panic("err mclBnG1_getStr") + } + return string(buf[:n]) +} + +// Serialize -- +func (x *G1) Serialize() []byte { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnG1_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) + if n == 0 { + panic("err mclBnG1_serialize") + } + return buf[:n] +} + +// G1Neg -- +func G1Neg(out *G1, x *G1) { + C.mclBnG1_neg(out.getPointer(), x.getPointer()) +} + +// G1Dbl -- +func G1Dbl(out *G1, x *G1) { + C.mclBnG1_dbl(out.getPointer(), x.getPointer()) +} + +// G1Add -- +func G1Add(out *G1, x *G1, y *G1) { + C.mclBnG1_add(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G1Sub -- +func G1Sub(out *G1, x *G1, y *G1) { + C.mclBnG1_sub(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G1Mul -- +func G1Mul(out *G1, x *G1, y *Fr) { + C.mclBnG1_mul(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G1MulCT -- constant time (depending on bit lengh of y) +func G1MulCT(out *G1, x *G1, y *Fr) { + C.mclBnG1_mulCT(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G2 -- +type G2 struct { + v C.mclBnG2 +} + +// getPointer -- +func (x *G2) getPointer() (p *C.mclBnG2) { + // #nosec + return (*C.mclBnG2)(unsafe.Pointer(x)) +} + +// Clear -- +func (x *G2) Clear() { + // #nosec + C.mclBnG2_clear(x.getPointer()) +} + +// SetString -- +func (x *G2) SetString(s string, base int) error { + buf := []byte(s) + // #nosec + err := C.mclBnG2_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) + if err != 0 { + return fmt.Errorf("err mclBnG2_setStr %x", err) + } + return nil +} + +// Deserialize -- +func (x *G2) Deserialize(buf []byte) error { + // #nosec + err := C.mclBnG2_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err == 0 { + return fmt.Errorf("err mclBnG2_deserialize %x", buf) + } + return nil +} + +// IsEqual -- +func (x *G2) IsEqual(rhs *G2) bool { + return C.mclBnG2_isEqual(x.getPointer(), rhs.getPointer()) == 1 +} + +// IsZero -- +func (x *G2) IsZero() bool { + return C.mclBnG2_isZero(x.getPointer()) == 1 +} + +// HashAndMapTo -- +func (x *G2) HashAndMapTo(buf []byte) error { + // #nosec + err := C.mclBnG2_hashAndMapTo(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err != 0 { + return fmt.Errorf("err mclBnG2_hashAndMapTo %x", err) + } + return nil +} + +// GetString -- +func (x *G2) GetString(base int) string { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnG2_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) + if n == 0 { + panic("err mclBnG2_getStr") + } + return string(buf[:n]) +} + +// Serialize -- +func (x *G2) Serialize() []byte { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnG2_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) + if n == 0 { + panic("err mclBnG2_serialize") + } + return buf[:n] +} + +// G2Neg -- +func G2Neg(out *G2, x *G2) { + C.mclBnG2_neg(out.getPointer(), x.getPointer()) +} + +// G2Dbl -- +func G2Dbl(out *G2, x *G2) { + C.mclBnG2_dbl(out.getPointer(), x.getPointer()) +} + +// G2Add -- +func G2Add(out *G2, x *G2, y *G2) { + C.mclBnG2_add(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G2Sub -- +func G2Sub(out *G2, x *G2, y *G2) { + C.mclBnG2_sub(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// G2Mul -- +func G2Mul(out *G2, x *G2, y *Fr) { + C.mclBnG2_mul(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GT -- +type GT struct { + v C.mclBnGT +} + +// getPointer -- +func (x *GT) getPointer() (p *C.mclBnGT) { + // #nosec + return (*C.mclBnGT)(unsafe.Pointer(x)) +} + +// Clear -- +func (x *GT) Clear() { + // #nosec + C.mclBnGT_clear(x.getPointer()) +} + +// SetInt64 -- +func (x *GT) SetInt64(v int64) { + // #nosec + C.mclBnGT_setInt(x.getPointer(), C.int64_t(v)) +} + +// SetString -- +func (x *GT) SetString(s string, base int) error { + buf := []byte(s) + // #nosec + err := C.mclBnGT_setStr(x.getPointer(), (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), C.int(base)) + if err != 0 { + return fmt.Errorf("err mclBnGT_setStr %x", err) + } + return nil +} + +// Deserialize -- +func (x *GT) Deserialize(buf []byte) error { + // #nosec + err := C.mclBnGT_deserialize(x.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + if err == 0 { + return fmt.Errorf("err mclBnGT_deserialize %x", buf) + } + return nil +} + +// IsEqual -- +func (x *GT) IsEqual(rhs *GT) bool { + return C.mclBnGT_isEqual(x.getPointer(), rhs.getPointer()) == 1 +} + +// IsZero -- +func (x *GT) IsZero() bool { + return C.mclBnGT_isZero(x.getPointer()) == 1 +} + +// IsOne -- +func (x *GT) IsOne() bool { + return C.mclBnGT_isOne(x.getPointer()) == 1 +} + +// GetString -- +func (x *GT) GetString(base int) string { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnGT_getStr((*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf)), x.getPointer(), C.int(base)) + if n == 0 { + panic("err mclBnGT_getStr") + } + return string(buf[:n]) +} + +// Serialize -- +func (x *GT) Serialize() []byte { + buf := make([]byte, 2048) + // #nosec + n := C.mclBnGT_serialize(unsafe.Pointer(&buf[0]), C.size_t(len(buf)), x.getPointer()) + if n == 0 { + panic("err mclBnGT_serialize") + } + return buf[:n] +} + +// GTNeg -- +func GTNeg(out *GT, x *GT) { + C.mclBnGT_neg(out.getPointer(), x.getPointer()) +} + +// GTInv -- +func GTInv(out *GT, x *GT) { + C.mclBnGT_inv(out.getPointer(), x.getPointer()) +} + +// GTAdd -- +func GTAdd(out *GT, x *GT, y *GT) { + C.mclBnGT_add(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GTSub -- +func GTSub(out *GT, x *GT, y *GT) { + C.mclBnGT_sub(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GTMul -- +func GTMul(out *GT, x *GT, y *GT) { + C.mclBnGT_mul(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GTDiv -- +func GTDiv(out *GT, x *GT, y *GT) { + C.mclBnGT_div(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GTPow -- +func GTPow(out *GT, x *GT, y *Fr) { + C.mclBnGT_pow(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// Pairing -- +func Pairing(out *GT, x *G1, y *G2) { + C.mclBn_pairing(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// FinalExp -- +func FinalExp(out *GT, x *GT) { + C.mclBn_finalExp(out.getPointer(), x.getPointer()) +} + +// MillerLoop -- +func MillerLoop(out *GT, x *G1, y *G2) { + C.mclBn_millerLoop(out.getPointer(), x.getPointer(), y.getPointer()) +} + +// GetUint64NumToPrecompute -- +func GetUint64NumToPrecompute() int { + return int(C.mclBn_getUint64NumToPrecompute()) +} + +// PrecomputeG2 -- +func PrecomputeG2(Qbuf []uint64, Q *G2) { + // #nosec + C.mclBn_precomputeG2((*C.uint64_t)(unsafe.Pointer(&Qbuf[0])), Q.getPointer()) +} + +// PrecomputedMillerLoop -- +func PrecomputedMillerLoop(out *GT, P *G1, Qbuf []uint64) { + // #nosec + C.mclBn_precomputedMillerLoop(out.getPointer(), P.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Qbuf[0]))) +} + +// PrecomputedMillerLoop2 -- +func PrecomputedMillerLoop2(out *GT, P1 *G1, Q1buf []uint64, P2 *G1, Q2buf []uint64) { + // #nosec + C.mclBn_precomputedMillerLoop2(out.getPointer(), P1.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Q1buf[0])), P1.getPointer(), (*C.uint64_t)(unsafe.Pointer(&Q1buf[0]))) +} + +// FrEvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... +func FrEvaluatePolynomial(y *Fr, c []Fr, x *Fr) error { + // #nosec + err := C.mclBn_FrEvaluatePolynomial(y.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer()) + if err != 0 { + return fmt.Errorf("err mclBn_FrEvaluatePolynomial") + } + return nil +} + +// G1EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... +func G1EvaluatePolynomial(y *G1, c []G1, x *Fr) error { + // #nosec + err := C.mclBn_G1EvaluatePolynomial(y.getPointer(), (*C.mclBnG1)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer()) + if err != 0 { + return fmt.Errorf("err mclBn_G1EvaluatePolynomial") + } + return nil +} + +// G2EvaluatePolynomial -- y = c[0] + c[1] * x + c[2] * x^2 + ... +func G2EvaluatePolynomial(y *G2, c []G2, x *Fr) error { + // #nosec + err := C.mclBn_G2EvaluatePolynomial(y.getPointer(), (*C.mclBnG2)(unsafe.Pointer(&c[0])), (C.size_t)(len(c)), x.getPointer()) + if err != 0 { + return fmt.Errorf("err mclBn_G2EvaluatePolynomial") + } + return nil +} + +// FrLagrangeInterpolation -- +func FrLagrangeInterpolation(out *Fr, xVec []Fr, yVec []Fr) error { + if len(xVec) != len(yVec) { + return fmt.Errorf("err FrLagrangeInterpolation:bad size") + } + // #nosec + err := C.mclBn_FrLagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnFr)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec))) + if err != 0 { + return fmt.Errorf("err FrLagrangeInterpolation") + } + return nil +} + +// G1LagrangeInterpolation -- +func G1LagrangeInterpolation(out *G1, xVec []Fr, yVec []G1) error { + if len(xVec) != len(yVec) { + return fmt.Errorf("err G1LagrangeInterpolation:bad size") + } + // #nosec + err := C.mclBn_G1LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG1)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec))) + if err != 0 { + return fmt.Errorf("err G1LagrangeInterpolation") + } + return nil +} + +// G2LagrangeInterpolation -- +func G2LagrangeInterpolation(out *G2, xVec []Fr, yVec []G2) error { + if len(xVec) != len(yVec) { + return fmt.Errorf("err G2LagrangeInterpolation:bad size") + } + // #nosec + err := C.mclBn_G2LagrangeInterpolation(out.getPointer(), (*C.mclBnFr)(unsafe.Pointer(&xVec[0])), (*C.mclBnG2)(unsafe.Pointer(&yVec[0])), (C.size_t)(len(xVec))) + if err != 0 { + return fmt.Errorf("err G2LagrangeInterpolation") + } + return nil +} -- cgit v1.2.3