diff --git a/element.go b/element.go new file mode 100644 index 0000000000000000000000000000000000000000..03bd8b8ae3ba91dc140b803ebecbae4f7e61d55c --- /dev/null +++ b/element.go @@ -0,0 +1,170 @@ +package pbc + +/* +#cgo LDFLAGS: /usr/local/lib/libpbc.a -lgmp +#include <pbc/pbc.h> +*/ +import "C" + +import ( + "errors" + "fmt" + "math/big" + "runtime" +) + +var ErrUnknownField = errors.New("unchecked element initialized in unknown field") + +type Element interface { + NewFieldElement() Element + + Set0() Element + Set1() Element + SetInt32(int32) Element + SetBig(*big.Int) Element + Set(Element) Element + + SetFromHash([]byte) Element + SetBytes([]byte) Element + SetXBytes([]byte) Element + SetCompressedBytes([]byte) Element + + SetString(s string, base int) (Element, bool) + + Format(fmt.State, rune) + Scan(fmt.ScanState, rune) error + + BigInt() *big.Int + String() string + + BytesLen() int + Bytes() []byte + XBytesLen() int + XBytes() []byte + CompressedBytesLen() int + CompressedBytes() []byte + + Len() int + Item(int) Element + X() *big.Int + Y() *big.Int + + Is0() bool + Is1() bool + IsSquare() bool + Sign() int + + Cmp(x Element) int + + Add(x, y Element) Element + Sub(x, y Element) Element + Mul(x, y Element) Element + MulBig(x Element, i *big.Int) Element + MulInt32(x Element, i int32) Element + MulZn(x, y Element) Element + Div(x, y Element) Element + Double(x Element) Element + Halve(x Element) Element + Square(x Element) Element + Neg(x Element) Element + Invert(x Element) Element + + PowBig(x Element, i *big.Int) Element + PowZn(x, i Element) Element + Pow2Big(x Element, i *big.Int, y Element, j *big.Int) Element + Pow2Zn(x, i, y, j Element) Element + Pow3Big(x Element, i *big.Int, y Element, j *big.Int, z Element, k *big.Int) Element + Pow3Zn(x, i, y, j, z, k Element) Element + + PreparePower() Power + + BruteForceDL(g, h Element) Element + PollardRhoDL(g, h Element) Element + + Rand() Element + + impl() *elementImpl +} + +type elementImpl struct { + pairing *pairingImpl + data *C.struct_element_s +} + +type checkedElement struct { + elementImpl + fieldPtr *C.struct_field_s + isInteger bool +} + +type Power interface { + PowBig(i *big.Int) Element + PowZn(i Element) Element +} + +type powerImpl struct { + target *elementImpl + data *C.struct_element_pp_s +} + +type checkedPower struct { + powerImpl +} + +func (pairing *pairingImpl) NewG1() Element { return makeChecked(pairing, G1, pairing.data.G1) } +func (pairing *pairingImpl) NewG2() Element { return makeChecked(pairing, G2, pairing.data.G2) } +func (pairing *pairingImpl) NewGT() Element { return makeChecked(pairing, GT, &pairing.data.GT[0]) } +func (pairing *pairingImpl) NewZr() Element { return makeChecked(pairing, Zr, &pairing.data.Zr[0]) } +func (pairing *pairingImpl) NewElement(field Field) Element { return makeElement(pairing, field) } + +func clearElement(element *elementImpl) { + println("clearelement") + C.element_clear(element.data) +} + +func initElement(element *elementImpl, pairing *pairingImpl, initialize bool, field Field) { + element.data = &C.struct_element_s{} + element.pairing = pairing + if initialize { + switch field { + case G1: + C.element_init_G1(element.data, pairing.data) + case G2: + C.element_init_G2(element.data, pairing.data) + case GT: + C.element_init_GT(element.data, pairing.data) + case Zr: + C.element_init_Zr(element.data, pairing.data) + default: + panic(ErrUnknownField) + } + } + runtime.SetFinalizer(element, clearElement) +} + +func makeElement(pairing *pairingImpl, field Field) *elementImpl { + element := &elementImpl{} + initElement(element, pairing, true, field) + return element +} + +func makeChecked(pairing *pairingImpl, field Field, fieldPtr *C.struct_field_s) *checkedElement { + element := &checkedElement{ + fieldPtr: fieldPtr, + isInteger: field == Zr, + } + initElement(&element.elementImpl, pairing, true, field) + return element +} + +func clearPower(power *powerImpl) { + println("clearpower") + C.element_pp_clear(power.data) +} + +func initPower(power *powerImpl, target *elementImpl) { + power.target = target + power.data = &C.struct_element_pp_s{} + C.element_pp_init(power.data, target.data) + runtime.SetFinalizer(power, clearPower) +} diff --git a/element_checked.go b/element_checked.go new file mode 100644 index 0000000000000000000000000000000000000000..de4dd76fa2451a129ca93981214c7ecf04bca66a --- /dev/null +++ b/element_checked.go @@ -0,0 +1,237 @@ +package pbc + +/* +#cgo LDFLAGS: /usr/local/lib/libpbc.a -lgmp +#include <pbc/pbc.h> +*/ +import "C" + +import ( + "errors" + "math/big" +) + +var ( + ErrIllegalOp = errors.New("operation is illegal for elements of this type") + ErrUncheckedOp = errors.New("unchecked element passed to checked operation") + ErrIncompatible = errors.New("elements are from incompatible fields or pairings") + ErrOutOfRange = errors.New("index out of range") + ErrInternal = errors.New("a severe internal error has lead to possible memory corruption") +) + +func (el *checkedElement) impl() *elementImpl { return &el.elementImpl } + +func element2Checked(x Element) *checkedElement { + checked, ok := x.(*checkedElement) + if !ok { + panic(ErrUncheckedOp) + } + return checked +} + +func (el *checkedElement) checkCompatible(other Element) { + otherChecked := element2Checked(other) + if el.fieldPtr != otherChecked.fieldPtr { + panic(ErrIncompatible) + } +} + +func (el *checkedElement) checkAllCompatible(elements ...Element) { + for _, other := range elements { + el.checkCompatible(other) + } +} + +func (el *checkedElement) checkInteger() { + if !el.isInteger { + panic(ErrIllegalOp) + } +} + +func (el *checkedElement) NewFieldElement() Element { + newElement := &checkedElement{} + *newElement = *el + initElement(&newElement.elementImpl, el.pairing, false, G1) + C.element_init_same_as(newElement.elementImpl.data, el.data) + return newElement +} + +func (el *checkedElement) SetInt32(i int32) Element { + el.checkInteger() + return el.elementImpl.SetInt32(i) +} + +func (el *checkedElement) SetBig(i *big.Int) Element { + el.checkInteger() + return el.elementImpl.SetBig(i) +} + +func (el *checkedElement) Set(src Element) Element { + el.checkCompatible(src) + return el.elementImpl.Set(src) +} + +func (el *checkedElement) BigInt() *big.Int { + el.checkInteger() + return el.elementImpl.BigInt() +} + +func checkedWrite(bytesWritten C.int, buffer []byte) []byte { + if int64(bytesWritten) > int64(len(buffer)) { + panic(ErrInternal) + } + return buffer +} + +func (el *checkedElement) Bytes() []byte { + buf := make([]byte, el.BytesLen()) + return checkedWrite(el.elementImpl.writeBytes(buf), buf) +} + +func (el *checkedElement) XBytes() []byte { + buf := make([]byte, el.XBytesLen()) + return checkedWrite(el.elementImpl.writeXBytes(buf), buf) +} + +func (el *checkedElement) CompressedBytes() []byte { + buf := make([]byte, el.CompressedBytesLen()) + return checkedWrite(el.elementImpl.writeCompressedBytes(buf), buf) +} + +func (el *checkedElement) Item(i int) Element { + if i >= el.Len() { + panic(ErrOutOfRange) + } + uncheckedData := el.elementImpl.Item(i).(*elementImpl) + item := &checkedElement{ + fieldPtr: uncheckedData.data.field, + isInteger: uncheckedData.Len() == 0, + } + item.elementImpl = *uncheckedData + return item +} + +func (el *checkedElement) Cmp(x Element) int { + el.checkCompatible(x) + return el.elementImpl.Cmp(x) +} + +func (el *checkedElement) Add(x Element, y Element) Element { + el.checkAllCompatible(x, y) + return el.elementImpl.Add(x, y) +} + +func (el *checkedElement) Sub(x, y Element) Element { + el.checkAllCompatible(x, y) + return el.elementImpl.Sub(x, y) +} + +func (el *checkedElement) Mul(x, y Element) Element { + el.checkAllCompatible(x, y) + return el.elementImpl.Mul(x, y) +} + +func (el *checkedElement) MulBig(x Element, i *big.Int) Element { + el.checkCompatible(x) + return el.elementImpl.MulBig(x, i) +} + +func (el *checkedElement) MulInt32(x Element, i int32) Element { + el.checkCompatible(x) + return el.elementImpl.MulInt32(x, i) +} + +func (el *checkedElement) MulZn(x, y Element) Element { + el.checkCompatible(x) + element2Checked(y).checkInteger() + return el.elementImpl.MulZn(x, y) +} + +func (el *checkedElement) Div(x, y Element) Element { + el.checkAllCompatible(x, y) + return el.elementImpl.Div(x, y) +} + +func (el *checkedElement) Double(x Element) Element { + el.checkCompatible(x) + return el.elementImpl.Double(x) +} + +func (el *checkedElement) Halve(x Element) Element { + el.checkCompatible(x) + return el.elementImpl.Halve(x) +} + +func (el *checkedElement) Square(x Element) Element { + el.checkCompatible(x) + return el.elementImpl.Square(x) +} + +func (el *checkedElement) Neg(x Element) Element { + el.checkCompatible(x) + return el.elementImpl.Neg(x) +} + +func (el *checkedElement) Invert(x Element) Element { + el.checkCompatible(x) + return el.elementImpl.Invert(x) +} + +func (el *checkedElement) PowBig(x Element, i *big.Int) Element { + el.checkCompatible(x) + return el.elementImpl.PowBig(x, i) +} + +func (el *checkedElement) PowZn(x, i Element) Element { + el.checkCompatible(x) + element2Checked(i).checkInteger() + return el.elementImpl.PowZn(x, i) +} + +func (el *checkedElement) Pow2Big(x Element, i *big.Int, y Element, j *big.Int) Element { + el.checkAllCompatible(x, y) + return el.elementImpl.Pow2Big(x, i, y, j) +} + +func (el *checkedElement) Pow2Zn(x, i, y, j Element) Element { + el.checkAllCompatible(x, y) + element2Checked(i).checkInteger() + element2Checked(j).checkInteger() + return el.elementImpl.Pow2Zn(x, i, y, j) +} + +func (el *checkedElement) Pow3Big(x Element, i *big.Int, y Element, j *big.Int, z Element, k *big.Int) Element { + el.checkAllCompatible(x, y, z) + return el.elementImpl.Pow3Big(x, i, y, j, z, k) +} + +func (el *checkedElement) Pow3Zn(x, i, y, j, z, k Element) Element { + el.checkAllCompatible(x, y, z) + element2Checked(i).checkInteger() + element2Checked(j).checkInteger() + element2Checked(k).checkInteger() + return el.elementImpl.Pow3Zn(x, i, y, j, z, k) +} + +func (el *checkedElement) PreparePower() Power { + power := &checkedPower{} + initPower(&power.powerImpl, &el.elementImpl) + return power +} + +func (power *checkedPower) PowZn(i Element) Element { + element2Checked(i).checkInteger() + return power.powerImpl.PowZn(i) +} + +func (el *checkedElement) BruteForceDL(g, h Element) Element { + el.checkInteger() + element2Checked(g).checkCompatible(h) + return el.elementImpl.BruteForceDL(g, h) +} + +func (el *checkedElement) PollardRhoDL(g, h Element) Element { + el.checkInteger() + element2Checked(g).checkCompatible(h) + return el.elementImpl.PollardRhoDL(g, h) +} diff --git a/element_fmt.go b/element_fmt.go new file mode 100644 index 0000000000000000000000000000000000000000..055746354544222ba1ce9c00945bfd4fbc8d1bb0 --- /dev/null +++ b/element_fmt.go @@ -0,0 +1,184 @@ +package pbc + +/* +#cgo LDFLAGS: /usr/local/lib/libpbc.a -lgmp +#include <pbc/pbc.h> + +int element_out_str_wrapper(char** bufp, size_t* sizep, int base, element_t e) { + FILE* handle = open_memstream(bufp, sizep); + if (!handle) return 0; + element_out_str(handle, base, e); + fclose(handle); + return 1; +} +*/ +import "C" + +import ( + "bytes" + "errors" + "fmt" + "io" + "unsafe" +) + +var ( + ErrBadInput = errors.New("invalid element format during scan") + ErrBadVerb = errors.New("invalid verb specified for scan") +) + +func (el *elementImpl) errorFormat(f fmt.State, c rune, err string) { + fmt.Fprintf(f, "%%!%c(%s pbc.Element)", c, err) +} + +func (el *elementImpl) nativeFormat(f fmt.State, c rune) { + base := 10 + if width, ok := f.Width(); ok { + if width < 2 || width > 36 { + el.errorFormat(f, c, "BADBASE") + return + } + base = width + } + var buf *C.char + var bufLen C.size_t + if C.element_out_str_wrapper(&buf, &bufLen, C.int(base), el.data) == 0 { + el.errorFormat(f, c, "INTERNALERROR") + return + } + str := C.GoStringN(buf, C.int(bufLen)) + C.free(unsafe.Pointer(buf)) + fmt.Fprintf(f, "%s", str) +} + +func (el *elementImpl) customFormat(f fmt.State, c rune) { + count := el.Len() + if count == 0 { + el.BigInt().Format(f, c) + } else { + fmt.Fprintf(f, "[") + for i := 0; i < count; i++ { + el.Item(i).impl().customFormat(f, c) + if i+1 < count { + fmt.Fprintf(f, ", ") + } + } + fmt.Fprintf(f, "]") + } +} + +func (el *elementImpl) Format(f fmt.State, c rune) { + switch c { + case 'v': + if f.Flag('#') { + fmt.Fprintf(f, "pbc.Element{Checked: false, Pairing: %p, Addr: %p}", el.pairing, el) + break + } + fallthrough + case 's': + el.nativeFormat(f, c) + case 'd', 'b', 'o', 'x', 'X': + el.customFormat(f, c) + default: + el.errorFormat(f, c, "BADVERB") + } +} + +func (el *checkedElement) Format(f fmt.State, c rune) { + if c == 'v' && f.Flag('#') { + fmt.Fprintf(f, "pbc.Element{Checked: true, Integer: %t, Field: %p, Pairing: %p, Addr: %p}", el.isInteger, el.fieldPtr, el.pairing, el) + } else { + el.elementImpl.Format(f, c) + } +} + +func (el *elementImpl) String() string { + return fmt.Sprintf("%s", el) +} + +func (el *elementImpl) Scan(state fmt.ScanState, verb rune) error { + if verb != 's' && verb != 'v' { + return ErrBadVerb + } + base, ok := state.Width() + if !ok { + base = 10 + } else if base < 2 || base > 36 { + return ErrBadVerb + } + maxDigit := '9' + maxAlpha := 'z' + if base < 10 { + maxDigit = rune('0' + (base - 1)) + } + if base < 36 { + maxAlpha = rune('a' + (base - 11)) + } + + state.SkipSpace() + + tokensFound := make([]uint, 0, 5) + inToken := false + justDescended := false + expectTokenDone := false + var buf bytes.Buffer + +ReadLoop: + for { + r, _, err := state.ReadRune() + if err != nil { + if err == io.EOF { + if len(tokensFound) == 0 { + break ReadLoop + } + return ErrBadInput + } + return err + } + buf.WriteRune(r) + + if expectTokenDone && r != ',' && r != ']' { + return ErrBadInput + } + expectTokenDone = false + + switch r { + case '[': + if inToken { + return ErrBadInput + } + tokensFound = append(tokensFound, 0) + case ']': + if !inToken || len(tokensFound) == 0 || tokensFound[len(tokensFound)-1] == 0 { + return ErrBadInput + } + tokensFound = tokensFound[:len(tokensFound)-1] + if len(tokensFound) == 0 { + break ReadLoop + } + case ',': + if len(tokensFound) == 0 || (!inToken && !justDescended) { + return ErrBadInput + } + tokensFound[len(tokensFound)-1]++ + inToken = false + state.SkipSpace() + case 'O': + if inToken { + return ErrBadInput + } + expectTokenDone = true + inToken = true + default: + if (r < '0' || r > maxDigit) && (r < 'a' || r > maxAlpha) { + return ErrBadInput + } + inToken = true + } + justDescended = (r == ']') + } + if _, ok := el.SetString(buf.String(), base); !ok { + return ErrBadInput + } + return nil +} diff --git a/element_unchecked.go b/element_unchecked.go new file mode 100644 index 0000000000000000000000000000000000000000..8da3acfbd85202a4b8d45646d44aa5256285044f --- /dev/null +++ b/element_unchecked.go @@ -0,0 +1,294 @@ +package pbc + +/* +#cgo LDFLAGS: /usr/local/lib/libpbc.a -lgmp +#include <pbc/pbc.h> +*/ +import "C" + +import ( + "math/big" + "unsafe" +) + +func (el *elementImpl) impl() *elementImpl { return el } + +func (el *elementImpl) NewFieldElement() Element { + newElement := &elementImpl{} + initElement(newElement, el.pairing, false, G1) + C.element_init_same_as(newElement.data, el.data) + return newElement +} + +func (el *elementImpl) Set0() Element { + C.element_set0(el.data) + return el +} + +func (el *elementImpl) Set1() Element { + C.element_set1(el.data) + return el +} + +func (el *elementImpl) SetInt32(i int32) Element { + C.element_set_si(el.data, C.long(i)) + return el +} + +func (el *elementImpl) SetBig(i *big.Int) Element { + C.element_set_mpz(el.data, &big2mpz(i)[0]) + return el +} + +func (el *elementImpl) Set(src Element) Element { + C.element_set(el.data, src.impl().data) + return el +} + +func (el *elementImpl) SetBytes(buf []byte) Element { + C.element_from_bytes(el.data, (*C.uchar)(unsafe.Pointer(&buf[0]))) + return el +} + +func (el *elementImpl) SetXBytes(buf []byte) Element { + C.element_from_bytes_x_only(el.data, (*C.uchar)(unsafe.Pointer(&buf[0]))) + return el +} + +func (el *elementImpl) SetCompressedBytes(buf []byte) Element { + C.element_from_bytes_compressed(el.data, (*C.uchar)(unsafe.Pointer(&buf[0]))) + return el +} + +func (el *elementImpl) SetFromHash(hash []byte) Element { + C.element_from_hash(el.data, unsafe.Pointer(&hash[0]), C.int(len(hash))) + return el +} + +func (el *elementImpl) SetString(s string, base int) (Element, bool) { + cstr := C.CString(s) + defer C.free(unsafe.Pointer(cstr)) + + if ok := C.element_set_str(el.data, cstr, C.int(base)); ok == 0 { + return nil, false + } + return el, true +} + +func (el *elementImpl) BigInt() *big.Int { + mpz := newmpz() + C.element_to_mpz(&mpz[0], el.data) + return mpz2big(mpz) +} + +func (el *elementImpl) BytesLen() int { + return int(C.element_length_in_bytes(el.data)) +} + +func (el *elementImpl) writeBytes(buf []byte) C.int { + return C.element_to_bytes((*C.uchar)(unsafe.Pointer(&buf[0])), el.data) +} + +func (el *elementImpl) Bytes() []byte { + buf := make([]byte, el.BytesLen()) + el.writeBytes(buf) + return buf +} + +func (el *elementImpl) XBytesLen() int { + return int(C.element_length_in_bytes_x_only(el.data)) +} + +func (el *elementImpl) writeXBytes(buf []byte) C.int { + return C.element_to_bytes_x_only((*C.uchar)(unsafe.Pointer(&buf[0])), el.data) +} + +func (el *elementImpl) XBytes() []byte { + buf := make([]byte, el.XBytesLen()) + el.writeXBytes(buf) + return buf +} + +func (el *elementImpl) CompressedBytesLen() int { + return int(C.element_length_in_bytes_compressed(el.data)) +} + +func (el *elementImpl) writeCompressedBytes(buf []byte) C.int { + return C.element_to_bytes_compressed((*C.uchar)(unsafe.Pointer(&buf[0])), el.data) +} + +func (el *elementImpl) CompressedBytes() []byte { + buf := make([]byte, el.CompressedBytesLen()) + el.writeCompressedBytes(buf) + return buf +} + +func (el *elementImpl) Len() int { + return int(C.element_item_count(el.data)) +} + +func (el *elementImpl) Item(i int) Element { + return &elementImpl{ + pairing: el.pairing, + data: C.element_item(el.data, C.int(i)), + } +} + +func (el *elementImpl) X() *big.Int { + return el.Item(0).BigInt() +} + +func (el *elementImpl) Y() *big.Int { + return el.Item(1).BigInt() +} + +func (el *elementImpl) Is0() bool { + return C.element_is0(el.data) != 0 +} + +func (el *elementImpl) Is1() bool { + return C.element_is1(el.data) != 0 +} + +func (el *elementImpl) IsSquare() bool { + return C.element_is_sqr(el.data) != 0 +} + +func normalizeSign(sign int64) int { + if sign > 0 { + return 1 + } + if sign < 0 { + return -1 + } + return 0 +} + +func (el *elementImpl) Sign() int { + return normalizeSign(int64(C.element_sign(el.data))) +} + +func (el *elementImpl) Cmp(x Element) int { + return normalizeSign(int64(C.element_cmp(el.data, x.impl().data))) +} + +func (el *elementImpl) Add(x, y Element) Element { + C.element_add(el.data, x.impl().data, y.impl().data) + return el +} + +func (el *elementImpl) Sub(x, y Element) Element { + C.element_sub(el.data, x.impl().data, y.impl().data) + return el +} + +func (el *elementImpl) Mul(x, y Element) Element { + C.element_mul(el.data, x.impl().data, y.impl().data) + return el +} + +func (el *elementImpl) MulBig(x Element, i *big.Int) Element { + C.element_mul_mpz(el.data, x.impl().data, &big2mpz(i)[0]) + return el +} + +func (el *elementImpl) MulInt32(x Element, i int32) Element { + C.element_mul_si(el.data, x.impl().data, C.long(i)) + return el +} + +func (el *elementImpl) MulZn(x, y Element) Element { + C.element_mul_zn(el.data, x.impl().data, y.impl().data) + return el +} + +func (el *elementImpl) Div(x, y Element) Element { + C.element_div(el.data, x.impl().data, y.impl().data) + return el +} + +func (el *elementImpl) Double(x Element) Element { + C.element_double(el.data, x.impl().data) + return el +} + +func (el *elementImpl) Halve(x Element) Element { + C.element_halve(el.data, x.impl().data) + return el +} + +func (el *elementImpl) Square(x Element) Element { + C.element_square(el.data, x.impl().data) + return el +} + +func (el *elementImpl) Neg(x Element) Element { + C.element_neg(el.data, x.impl().data) + return el +} + +func (el *elementImpl) Invert(x Element) Element { + C.element_invert(el.data, x.impl().data) + return el +} + +func (el *elementImpl) PowBig(x Element, i *big.Int) Element { + C.element_pow_mpz(el.data, x.impl().data, &big2mpz(i)[0]) + return el +} + +func (el *elementImpl) PowZn(x, i Element) Element { + C.element_pow_zn(el.data, x.impl().data, i.impl().data) + return el +} + +func (el *elementImpl) Pow2Big(x Element, i *big.Int, y Element, j *big.Int) Element { + C.element_pow2_mpz(el.data, x.impl().data, &big2mpz(i)[0], y.impl().data, &big2mpz(j)[0]) + return el +} + +func (el *elementImpl) Pow2Zn(x, i, y, j Element) Element { + C.element_pow2_zn(el.data, x.impl().data, i.impl().data, y.impl().data, j.impl().data) + return el +} + +func (el *elementImpl) Pow3Big(x Element, i *big.Int, y Element, j *big.Int, z Element, k *big.Int) Element { + C.element_pow3_mpz(el.data, x.impl().data, &big2mpz(i)[0], y.impl().data, &big2mpz(j)[0], z.impl().data, &big2mpz(k)[0]) + return el +} + +func (el *elementImpl) Pow3Zn(x, i, y, j, z, k Element) Element { + C.element_pow3_zn(el.data, x.impl().data, i.impl().data, y.impl().data, j.impl().data, z.impl().data, k.impl().data) + return el +} + +func (el *elementImpl) PreparePower() Power { + power := &powerImpl{} + initPower(power, el) + return power +} + +func (power *powerImpl) PowBig(i *big.Int) Element { + C.element_pp_pow(power.target.data, &big2mpz(i)[0], power.data) + return power.target +} + +func (power *powerImpl) PowZn(i Element) Element { + C.element_pp_pow_zn(power.target.data, i.impl().data, power.data) + return power.target +} + +func (el *elementImpl) BruteForceDL(g, h Element) Element { + C.element_dlog_brute_force(el.data, g.impl().data, h.impl().data) + return el +} + +func (el *elementImpl) PollardRhoDL(g, h Element) Element { + C.element_dlog_pollard_rho(el.data, g.impl().data, h.impl().data) + return el +} + +func (el *elementImpl) Rand() Element { + C.element_random(el.data) + return el +} diff --git a/generation.go b/generation.go index 2ee46a6effcb2bd26afedf57d6f184b970887878..368013593e602940b58c2245d79d2dc98f593765 100644 --- a/generation.go +++ b/generation.go @@ -19,7 +19,7 @@ void genPairingD(pbc_param_ptr p, unsigned int D, unsigned int bitlimit) { } void genPairingG(pbc_param_ptr p, unsigned int D, unsigned int bitlimit) { - pbc_cm_search_d(acceptPairingG, p, D, bitlimit); + pbc_cm_search_g(acceptPairingG, p, D, bitlimit); } */ import "C" diff --git a/gmp_big.go b/gmp_big.go index c4378683cc81046ee2cbde418d7bf936a8d4124d..1f8baadc6dde6806d04bf0289e60f4d90296788e 100644 --- a/gmp_big.go +++ b/gmp_big.go @@ -17,6 +17,7 @@ var wordSize C.size_t var bitsPerWord C.size_t func clearmpz(x *C.mpz_t) { + println("clearmpz") C.mpz_clear(&x[0]) } diff --git a/pairing.go b/pairing.go index a17a803034f06cd9a8a9059b29ab5c8a7a3033d5..4b60eb04c3336a6509af713c89edd321463b290d 100644 --- a/pairing.go +++ b/pairing.go @@ -6,29 +6,107 @@ package pbc */ import "C" -import "io" -import "runtime" +import ( + "bytes" + "io" + "runtime" +) -type Pairing interface{} +type Field int + +const ( + G1 Field = iota + G2 Field = iota + GT Field = iota + Zr Field = iota +) + +type Pairing interface { + IsSymmetric() bool + + G1Length() uint + G1XLength() uint + G1CompressedLength() uint + G2Length() uint + G2XLength() uint + G2CompressedLength() uint + GTLength() uint + ZrLength() uint + + NewG1() Element + NewG2() Element + NewGT() Element + NewZr() Element + NewElement(Field) Element +} type pairingImpl struct { - data C.pairing_ptr + data *C.struct_pairing_s } -func pairingFinalize(p *pairingImpl) { +func NewPairing(params io.Reader) (Pairing, error) { + buf := new(bytes.Buffer) + buf.ReadFrom(params) + return NewPairingFromString(buf.String()) +} +func NewPairingFromString(params string) (Pairing, error) { + p, err := NewParamsFromString(params) + if err != nil { + return nil, err + } + return NewPairingFromParams(p), nil } -func NewPairing(params io.Reader) Pairing { - x := &pairingImpl{} - runtime.SetFinalizer(x, pairingFinalize) - return x +func NewPairingFromParams(params Params) Pairing { + pairing := makePairing() + C.pairing_init_pbc_param(pairing.data, params.(*C.struct_pbc_param_s)) + return pairing } -func NewPairingFromString(params string) Pairing { - return nil +func (pairing *pairingImpl) IsSymmetric() bool { + return C.pairing_is_symmetric(pairing.data) != 0 } -func NewPairingFromParams(params Params) Pairing { - return nil +func (pairing *pairingImpl) G1Length() uint { + return uint(C.pairing_length_in_bytes_G1(pairing.data)) +} + +func (pairing *pairingImpl) G1XLength() uint { + return uint(C.pairing_length_in_bytes_x_only_G1(pairing.data)) +} + +func (pairing *pairingImpl) G1CompressedLength() uint { + return uint(C.pairing_length_in_bytes_compressed_G1(pairing.data)) +} + +func (pairing *pairingImpl) G2Length() uint { + return uint(C.pairing_length_in_bytes_G2(pairing.data)) +} + +func (pairing *pairingImpl) G2XLength() uint { + return uint(C.pairing_length_in_bytes_x_only_G2(pairing.data)) +} + +func (pairing *pairingImpl) G2CompressedLength() uint { + return uint(C.pairing_length_in_bytes_compressed_G2(pairing.data)) +} + +func (pairing *pairingImpl) GTLength() uint { + return uint(C.pairing_length_in_bytes_GT(pairing.data)) +} + +func (pairing *pairingImpl) ZrLength() uint { + return uint(C.pairing_length_in_bytes_Zr(pairing.data)) +} + +func clearPairing(pairing *pairingImpl) { + println("clearpairing") + C.pairing_clear(pairing.data) +} + +func makePairing() *pairingImpl { + pairing := &pairingImpl{data: &C.struct_pairing_s{}} + runtime.SetFinalizer(pairing, clearPairing) + return pairing } diff --git a/params.go b/params.go index 81ea4a7c8b82b6d55a165e191e5765ebc2f4d783..c1a9e6dc32b826ef1c0e1bc6bf9437266302497a 100644 --- a/params.go +++ b/params.go @@ -4,7 +4,7 @@ package pbc #cgo LDFLAGS: /usr/local/lib/libpbc.a -lgmp #include <pbc/pbc.h> -int param_out_str(char** bufp, size_t* sizep, pbc_param_t p) { +int param_out_str_wrapper(char** bufp, size_t* sizep, pbc_param_t p) { FILE* handle = open_memstream(bufp, sizep); if (!handle) return 0; pbc_param_out_str(handle, p); @@ -29,8 +29,8 @@ type Params interface { String() string } -func NewParamsFromString(data string) (Pairing, error) { - cstr := C.CString(data) +func NewParamsFromString(s string) (Params, error) { + cstr := C.CString(s) defer C.free(unsafe.Pointer(cstr)) params := makeParams() @@ -52,7 +52,7 @@ func (params *C.struct_pbc_param_s) WriteTo(w io.Writer) (n int64, err error) { func (params *C.struct_pbc_param_s) String() string { var buf *C.char var bufLen C.size_t - if C.param_out_str(&buf, &bufLen, params) == 0 { + if C.param_out_str_wrapper(&buf, &bufLen, params) == 0 { return "" } str := C.GoStringN(buf, C.int(bufLen)) @@ -60,12 +60,13 @@ func (params *C.struct_pbc_param_s) String() string { return str } -func paramsFinalizer(params *C.struct_pbc_param_s) { +func clearParams(params *C.struct_pbc_param_s) { + println("clearparams") C.pbc_param_clear(params) } func makeParams() *C.struct_pbc_param_s { params := &C.struct_pbc_param_s{} - runtime.SetFinalizer(params, paramsFinalizer) + runtime.SetFinalizer(params, clearParams) return params }