github.com/cloudflare/circl@v1.5.0/group/ristretto255.go (about)

     1  package group
     2  
     3  import (
     4  	"crypto"
     5  	_ "crypto/sha512"
     6  	"fmt"
     7  	"io"
     8  	"math/big"
     9  
    10  	r255 "github.com/bwesterb/go-ristretto"
    11  	"github.com/cloudflare/circl/expander"
    12  	"github.com/cloudflare/circl/internal/conv"
    13  )
    14  
    15  // Ristretto255 is a quotient group generated from the edwards25519 curve.
    16  var Ristretto255 Group = ristrettoGroup{}
    17  
    18  type ristrettoGroup struct{}
    19  
    20  func (g ristrettoGroup) String() string {
    21  	return "ristretto255"
    22  }
    23  
    24  func (g ristrettoGroup) Params() *Params {
    25  	return &Params{32, 32, 32}
    26  }
    27  
    28  type ristrettoElement struct {
    29  	p r255.Point
    30  }
    31  
    32  type ristrettoScalar struct {
    33  	s r255.Scalar
    34  }
    35  
    36  func (g ristrettoGroup) NewElement() Element {
    37  	return g.Identity()
    38  }
    39  
    40  func (g ristrettoGroup) NewScalar() Scalar {
    41  	return &ristrettoScalar{
    42  		s: r255.Scalar{},
    43  	}
    44  }
    45  
    46  func (g ristrettoGroup) Identity() Element {
    47  	var zero r255.Point
    48  	zero.SetZero()
    49  	return &ristrettoElement{
    50  		p: zero,
    51  	}
    52  }
    53  
    54  func (g ristrettoGroup) Generator() Element {
    55  	var base r255.Point
    56  	base.SetBase()
    57  	return &ristrettoElement{
    58  		p: base,
    59  	}
    60  }
    61  
    62  func (g ristrettoGroup) RandomElement(r io.Reader) Element {
    63  	var x r255.Point
    64  	x.Rand()
    65  	return &ristrettoElement{
    66  		p: x,
    67  	}
    68  }
    69  
    70  func (g ristrettoGroup) RandomScalar(io.Reader) Scalar {
    71  	var x r255.Scalar
    72  	x.Rand()
    73  	return &ristrettoScalar{
    74  		s: x,
    75  	}
    76  }
    77  
    78  func (g ristrettoGroup) RandomNonZeroScalar(io.Reader) Scalar {
    79  	var s r255.Scalar
    80  	for {
    81  		s.Rand()
    82  		if s.IsNonZeroI() == 1 {
    83  			return &ristrettoScalar{s}
    84  		}
    85  	}
    86  }
    87  
    88  func (g ristrettoGroup) HashToElementNonUniform(b, dst []byte) Element {
    89  	return g.HashToElement(b, dst)
    90  }
    91  
    92  func (g ristrettoGroup) HashToElement(msg, dst []byte) Element {
    93  	// Compliant with draft-irtf-cfrg-hash-to-curve.
    94  	// Appendix B - Hashing to ristretto255
    95  	// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-14#appendix-B
    96  	// SuiteID: ristretto255_XMD:SHA-512_R255MAP_RO_
    97  	var buf [32]byte
    98  	xmd := expander.NewExpanderMD(crypto.SHA512, dst)
    99  	uniformBytes := xmd.Expand(msg, 64)
   100  	copy(buf[:], uniformBytes[:32])
   101  	p0 := new(r255.Point).SetElligator(&buf)
   102  	copy(buf[:], uniformBytes[32:])
   103  	p1 := new(r255.Point).SetElligator(&buf)
   104  	p0.Add(p0, p1)
   105  
   106  	return &ristrettoElement{*p0}
   107  }
   108  
   109  func (g ristrettoGroup) HashToScalar(msg, dst []byte) Scalar {
   110  	// Adapted to be compliant with draft-irtf-cfrg-voprf
   111  	// Section 4.1.1 - OPRF(ristretto255, SHA-512)
   112  	// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-voprf-09#section-4.1.1
   113  	var uniformBytes [64]byte
   114  	xmd := expander.NewExpanderMD(crypto.SHA512, dst)
   115  	copy(uniformBytes[:], xmd.Expand(msg, 64))
   116  	s := g.NewScalar()
   117  	s.(*ristrettoScalar).s.SetReduced(&uniformBytes)
   118  	return s
   119  }
   120  
   121  func (e *ristrettoElement) Group() Group { return Ristretto255 }
   122  
   123  func (e *ristrettoElement) String() string { return fmt.Sprintf("%x", e.p.Bytes()) }
   124  
   125  func (e *ristrettoElement) IsIdentity() bool {
   126  	var zero r255.Point
   127  	zero.SetZero()
   128  	return e.p.Equals(&zero)
   129  }
   130  
   131  func (e *ristrettoElement) IsEqual(x Element) bool {
   132  	return e.p.Equals(&x.(*ristrettoElement).p)
   133  }
   134  
   135  func (e *ristrettoElement) Set(x Element) Element {
   136  	e.p.Set(&x.(*ristrettoElement).p)
   137  	return e
   138  }
   139  
   140  func (e *ristrettoElement) Copy() Element {
   141  	return &ristrettoElement{*new(r255.Point).Set(&e.p)}
   142  }
   143  
   144  func (e *ristrettoElement) CMov(v int, x Element) Element {
   145  	if !(v == 0 || v == 1) {
   146  		panic(ErrSelector)
   147  	}
   148  	e.p.ConditionalSet(&x.(*ristrettoElement).p, int32(v))
   149  	return e
   150  }
   151  
   152  func (e *ristrettoElement) CSelect(v int, x Element, y Element) Element {
   153  	if !(v == 0 || v == 1) {
   154  		panic(ErrSelector)
   155  	}
   156  	e.p.ConditionalSet(&x.(*ristrettoElement).p, int32(v))
   157  	e.p.ConditionalSet(&y.(*ristrettoElement).p, int32(1-v))
   158  	return e
   159  }
   160  
   161  func (e *ristrettoElement) Add(x Element, y Element) Element {
   162  	e.p.Add(&x.(*ristrettoElement).p, &y.(*ristrettoElement).p)
   163  	return e
   164  }
   165  
   166  func (e *ristrettoElement) Dbl(x Element) Element {
   167  	return e.Add(x, x)
   168  }
   169  
   170  func (e *ristrettoElement) Neg(x Element) Element {
   171  	e.p.Neg(&x.(*ristrettoElement).p)
   172  	return e
   173  }
   174  
   175  func (e *ristrettoElement) Mul(x Element, y Scalar) Element {
   176  	e.p.ScalarMult(&x.(*ristrettoElement).p, &y.(*ristrettoScalar).s)
   177  	return e
   178  }
   179  
   180  func (e *ristrettoElement) MulGen(x Scalar) Element {
   181  	e.p.ScalarMultBase(&x.(*ristrettoScalar).s)
   182  	return e
   183  }
   184  
   185  func (e *ristrettoElement) MarshalBinaryCompress() ([]byte, error) {
   186  	return e.p.MarshalBinary()
   187  }
   188  
   189  func (e *ristrettoElement) MarshalBinary() ([]byte, error) {
   190  	return e.p.MarshalBinary()
   191  }
   192  
   193  func (e *ristrettoElement) UnmarshalBinary(data []byte) error {
   194  	return e.p.UnmarshalBinary(data)
   195  }
   196  
   197  func (s *ristrettoScalar) Group() Group                { return Ristretto255 }
   198  func (s *ristrettoScalar) String() string              { return conv.BytesLe2Hex(s.s.Bytes()) }
   199  func (s *ristrettoScalar) SetUint64(n uint64) Scalar   { s.s.SetUint64(n); return s }
   200  func (s *ristrettoScalar) SetBigInt(x *big.Int) Scalar { s.s.SetBigInt(x); return s }
   201  func (s *ristrettoScalar) IsZero() bool                { return s.s.IsNonZeroI() == 0 }
   202  func (s *ristrettoScalar) IsEqual(x Scalar) bool {
   203  	return s.s.Equals(&x.(*ristrettoScalar).s)
   204  }
   205  
   206  func (s *ristrettoScalar) Set(x Scalar) Scalar {
   207  	s.s.Set(&x.(*ristrettoScalar).s)
   208  	return s
   209  }
   210  
   211  func (s *ristrettoScalar) Copy() Scalar {
   212  	return &ristrettoScalar{*new(r255.Scalar).Set(&s.s)}
   213  }
   214  
   215  func (s *ristrettoScalar) CMov(v int, x Scalar) Scalar {
   216  	if !(v == 0 || v == 1) {
   217  		panic(ErrSelector)
   218  	}
   219  	s.s.ConditionalSet(&x.(*ristrettoScalar).s, int32(v))
   220  	return s
   221  }
   222  
   223  func (s *ristrettoScalar) CSelect(v int, x Scalar, y Scalar) Scalar {
   224  	if !(v == 0 || v == 1) {
   225  		panic(ErrSelector)
   226  	}
   227  	s.s.ConditionalSet(&x.(*ristrettoScalar).s, int32(v))
   228  	s.s.ConditionalSet(&y.(*ristrettoScalar).s, int32(1-v))
   229  	return s
   230  }
   231  
   232  func (s *ristrettoScalar) Add(x Scalar, y Scalar) Scalar {
   233  	s.s.Add(&x.(*ristrettoScalar).s, &y.(*ristrettoScalar).s)
   234  	return s
   235  }
   236  
   237  func (s *ristrettoScalar) Sub(x Scalar, y Scalar) Scalar {
   238  	s.s.Sub(&x.(*ristrettoScalar).s, &y.(*ristrettoScalar).s)
   239  	return s
   240  }
   241  
   242  func (s *ristrettoScalar) Mul(x Scalar, y Scalar) Scalar {
   243  	s.s.Mul(&x.(*ristrettoScalar).s, &y.(*ristrettoScalar).s)
   244  	return s
   245  }
   246  
   247  func (s *ristrettoScalar) Neg(x Scalar) Scalar {
   248  	s.s.Neg(&x.(*ristrettoScalar).s)
   249  	return s
   250  }
   251  
   252  func (s *ristrettoScalar) Inv(x Scalar) Scalar {
   253  	s.s.Inverse(&x.(*ristrettoScalar).s)
   254  	return s
   255  }
   256  
   257  func (s *ristrettoScalar) MarshalBinary() ([]byte, error) {
   258  	return s.s.MarshalBinary()
   259  }
   260  
   261  func (s *ristrettoScalar) UnmarshalBinary(data []byte) error {
   262  	return s.s.UnmarshalBinary(data)
   263  }