diff options
Diffstat (limited to 'curve')
-rw-r--r-- | curve/curve.go | 61 | ||||
-rw-r--r-- | curve/ed25519.go | 132 |
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()) +} |