diff --git a/ristretto255.go b/ristretto255.go index 91f5efc..064bc1d 100644 --- a/ristretto255.go +++ b/ristretto255.go @@ -14,6 +14,7 @@ package ristretto255 import ( "bytes" + "encoding/base64" "errors" "github.com/gtank/ristretto255/internal/edwards25519" @@ -362,3 +363,24 @@ func (e *Element) Base() *Element { e.r.Set(&edwards25519.B) return e } + +// MarshalText implements encoding/TextMarshaler interface +func (e *Element) MarshalText() (text []byte, err error) { + b := e.Encode([]byte{}) + return []byte(base64.StdEncoding.EncodeToString(b)), nil +} + +// UnmarshalText implements encoding/TextMarshaler interface +func (e *Element) UnmarshalText(text []byte) error { + eb, err := base64.StdEncoding.DecodeString(string(text)) + if err == nil { + return e.Decode(eb) + } + return err +} + +// String implements the Stringer interface +func (e *Element) String() string { + result, _ := e.MarshalText() + return string(result) +} diff --git a/ristretto255_test.go b/ristretto255_test.go index f802eda..42b7aac 100644 --- a/ristretto255_test.go +++ b/ristretto255_test.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/sha512" "encoding/hex" + "encoding/json" "testing" "github.com/gtank/ristretto255/internal/radix51" @@ -240,3 +241,37 @@ func TestRistrettoFromUniformBytesTestVectors(t *testing.T) { } } } + +func TestMarshalScalar(t *testing.T) { + x := new(Scalar) + // generate an arbitrary scalar + xbytes := sha512.Sum512([]byte("Hello World")) + x.FromUniformBytes(xbytes[:]) + text, err := json.Marshal(x) + if err != nil { + t.Fatalf("Could not marshal json: %v", err) + } + t.Logf("json: %s", text) + y := new(Scalar) + err = json.Unmarshal(text, y) + if err != nil || y.Equal(x) == 0 { + t.Fatalf("Error unmarshaling scalar from json: %s %v", text, err) + } +} + +func TestMarshalElement(t *testing.T) { + x := new(Element) + // generate an arbitrary element + xbytes := sha512.Sum512([]byte("Hello World")) + x.FromUniformBytes(xbytes[:]) + text, err := json.Marshal(x) + if err != nil { + t.Fatalf("Could not marshal json: %v", err) + } + t.Logf("json: %s", text) + y := new(Element) + err = json.Unmarshal(text, y) + if err != nil || y.Equal(x) == 0 { + t.Fatalf("Error unmarshaling element from json: %s %v", text, err) + } +} diff --git a/scalar.go b/scalar.go index 0b7531f..a945156 100644 --- a/scalar.go +++ b/scalar.go @@ -5,6 +5,7 @@ package ristretto255 import ( + "encoding/base64" "github.com/gtank/ristretto255/internal/scalar" ) @@ -82,3 +83,24 @@ func (s *Scalar) Zero() *Scalar { s.s = scalar.Scalar{} return s } + +// MarshalText implements encoding/TextMarshaler interface +func (s *Scalar) MarshalText() (text []byte, err error) { + b := s.Encode([]byte{}) + return []byte(base64.StdEncoding.EncodeToString(b)), nil +} + +// UnmarshalText implements encoding/TextMarshaler interface +func (s *Scalar) UnmarshalText(text []byte) error { + sb, err := base64.StdEncoding.DecodeString(string(text)) + if err == nil { + return s.Decode(sb) + } + return err +} + +// String implements the Stringer interface +func (s *Scalar) String() string { + result, _ := s.MarshalText() + return string(result) +}