aboutsummaryrefslogtreecommitdiff
path: root/curve
diff options
context:
space:
mode:
authorÖzgür Kesim <oec@codeblau.de>2024-03-21 19:02:20 +0100
committerÖzgür Kesim <oec@codeblau.de>2024-03-21 19:02:20 +0100
commit989d09c8511eb10f2af06977d210deff39b6ff9e (patch)
treed360f2e3aa06d0e6dc2eaaac62274ca602d8821c /curve
parent458f9b7172148a272b23d61747f0758bf21dbf1f (diff)
veto, curve: Added an abstraction layer for elliptic curves
This will allow to easily swap various curves and implementations, for benchmarking, f.e.
Diffstat (limited to 'curve')
-rw-r--r--curve/curve.go61
-rw-r--r--curve/ed25519.go132
2 files changed, 193 insertions, 0 deletions
diff --git a/curve/curve.go b/curve/curve.go
new file mode 100644
index 0000000..a194cde
--- /dev/null
+++ b/curve/curve.go
@@ -0,0 +1,61 @@
+// This package implements an abstraction for various
+// elliptic curve primitives, as multiplicative group.
+package curve
+
+import "io"
+
+type Data interface {
+ Bytes() []byte
+ String() string
+}
+
+type SomeScalar[S Data] interface {
+ Add(S) S
+ Sub(S) S
+ Mult(S) S
+ Equal(S) bool
+
+ // Maybe later:
+ // Invert(S) S
+ // Negate(S) S
+}
+
+type ScalarReader[S any] interface {
+ RandomScalar() S
+ ScalarFromReader(io.Reader) (S, error)
+ ScalarFromBytes([]byte) (S, error)
+}
+
+type MultiplicativeCurve[S SomeScalar[s], s Data, P MPoint[S, s, p], p Data] interface {
+ ScalarReader[S]
+
+ Identity() P
+ Generator() P
+ Product([]P) P
+ Exp(S) P
+}
+
+type MPoint[S SomeScalar[s], s Data, P Data] interface {
+ Mult(P) P
+ Div(P) P
+ Inv() P
+ Exp(S) P
+ Equal(P) bool
+}
+
+// For additive formulation of the curve, use these interfaces:
+type AdditiveCurve[S SomeScalar[s], s Data, P APoint[S, s, p], p Data] interface {
+ ScalarReader[S]
+ Zero() P
+ Generator() P
+ Sum([]P) P
+ Mul(S) P
+}
+
+type APoint[S SomeScalar[s], s Data, P Data] interface {
+ Add(P) P
+ Sub(P) P
+ Neg(P) P
+ ScalarMult(S) P
+ Equal(P) bool
+} \ No newline at end of file
diff --git a/curve/ed25519.go b/curve/ed25519.go
new file mode 100644
index 0000000..e8e380d
--- /dev/null
+++ b/curve/ed25519.go
@@ -0,0 +1,132 @@
+// Implementation of a MultiplicateCurve, using filippo.io/edwards25519.
+// Note that the implementation in edwards25519 uses addition for the group operation,
+// while we are exposing a multiplicative version of it.
+package curve
+
+import (
+ "crypto/rand"
+ "encoding/base64"
+ "io"
+
+ ed "filippo.io/edwards25519"
+)
+
+var Curve25519 = &c25519{}
+
+type Curve25519Scalar = scalar
+type Curve25519Point = point
+
+type c25519 struct{}
+type scalar ed.Scalar
+type point ed.Point
+
+var _ MPoint[*scalar, *scalar, *point] = (*point)(nil)
+var _ MultiplicativeCurve[*scalar, *scalar, *point, *point] = Curve25519
+var _ SomeScalar[*scalar] = (*scalar)(nil)
+
+var b64 = base64.StdEncoding.WithPadding(base64.NoPadding)
+
+func (s *scalar) Bytes() []byte {
+ return ((*ed.Scalar)(s)).Bytes()
+}
+
+func (s *scalar) Equal(t *scalar) bool {
+ return ((*ed.Scalar)(s)).Equal((*ed.Scalar)(t)) == 1
+}
+
+func (s *scalar) String() string {
+ return b64.EncodeToString(s.Bytes())
+}
+
+func (s *scalar) Add(t *scalar) *scalar {
+ return (*scalar)(new(ed.Scalar).Add((*ed.Scalar)(s), (*ed.Scalar)(t)))
+}
+
+func (s *scalar) Sub(t *scalar) *scalar {
+ return (*scalar)(new(ed.Scalar).Subtract((*ed.Scalar)(s), (*ed.Scalar)(t)))
+}
+
+func (s *scalar) Mult(t *scalar) *scalar {
+ return (*scalar)(new(ed.Scalar).Multiply((*ed.Scalar)(s), (*ed.Scalar)(t)))
+}
+
+func (c *c25519) ScalarFromReader(random io.Reader) (*scalar, error) {
+ var buf [64]byte
+ if random == nil {
+ random = rand.Reader
+ }
+ random.Read(buf[:])
+ return c.ScalarFromBytes(buf[:])
+}
+
+func (c *c25519) RandomScalar() *scalar {
+ for i := 0; i < 3; i++ {
+ if s, e := c.ScalarFromReader(nil); e == nil {
+ return s
+ }
+ }
+ panic("couldn't generate scalar")
+}
+
+func (c *c25519) ScalarFromBytes(b []byte) (*scalar, error) {
+ s, e := new(ed.Scalar).SetUniformBytes(b)
+ return (*scalar)(s), e
+}
+
+func (c *c25519) Exp(s *scalar) *point {
+ p := new(ed.Point).ScalarBaseMult((*ed.Scalar)(s))
+ return (*point)(p)
+}
+
+func (c *c25519) Identity() *point {
+ return (*point)(ed.NewIdentityPoint())
+}
+
+func (c *c25519) Generator() *point {
+ return (*point)(ed.NewGeneratorPoint())
+}
+
+func (c *c25519) Product(pts []*point) (product *point) {
+ product = c.Identity()
+ for _, p := range pts {
+ product = product.Mult(p)
+ }
+ return product
+}
+
+// Return P^n , for n Sc, and P Pt
+func (p *point) Exp(s *scalar) *point {
+ r := new(ed.Point).ScalarMult((*ed.Scalar)(s), (*ed.Point)(p))
+ return (*point)(r)
+}
+
+func (p *point) Bytes() []byte {
+ return ((*ed.Point)(p)).Bytes()
+}
+
+// Return p (*) q in group
+func (p *point) Mult(q *point) *point {
+ r := new(ed.Point).Add((*ed.Point)(p), (*ed.Point)(q))
+ return (*point)(r)
+}
+
+// Return p (/) q in group
+func (p *point) Div(q *point) *point {
+ r := new(ed.Point).Subtract((*ed.Point)(p), (*ed.Point)(q))
+ return (*point)(r)
+}
+
+// Return p^(-1)
+func (p *point) Inv() *point {
+ n := new(ed.Point).Negate((*ed.Point)(p))
+ return (*point)(n)
+}
+
+func (p *point) Equal(q *point) bool {
+ return ((*ed.Point)(p)).Equal((*ed.Point)(q)) == 1
+
+}
+
+func (p *point) String() string {
+ return b64.EncodeToString(p.Bytes())
+}