github.com/cloudflare/circl@v1.5.0/ecc/bls12381/ff/scalar.go (about) 1 package ff 2 3 import ( 4 "io" 5 6 "github.com/cloudflare/circl/internal/conv" 7 ) 8 9 // ScalarSize is the length in bytes of a Scalar. 10 const ScalarSize = 32 11 12 // scMont represents an element in the Montgomery domain (little-endian). 13 type scMont = [ScalarSize / 8]uint64 14 15 // scRaw represents a scalar in the integers domain (little-endian). 16 type scRaw = [ScalarSize / 8]uint64 17 18 // Scalar represents positive integers less than ScalarOrder. 19 type Scalar struct{ i scMont } 20 21 func (z Scalar) String() string { x := z.fromMont(); return conv.Uint64Le2Hex(x[:]) } 22 func (z *Scalar) Set(x *Scalar) { z.i = x.i } 23 func (z *Scalar) SetUint64(n uint64) { z.toMont(&scRaw{n}) } 24 func (z *Scalar) SetOne() { z.SetUint64(1) } 25 func (z *Scalar) Random(r io.Reader) error { return randomInt(z.i[:], r, scOrder[:]) } 26 func (z Scalar) IsZero() int { return ctUint64Eq(z.i[:], (&scMont{})[:]) } 27 func (z Scalar) IsEqual(x *Scalar) int { return ctUint64Eq(z.i[:], x.i[:]) } 28 func (z *Scalar) Neg() { fiatScMontSub(&z.i, &scMont{}, &z.i) } 29 func (z *Scalar) Add(x, y *Scalar) { fiatScMontAdd(&z.i, &x.i, &y.i) } 30 func (z *Scalar) Sub(x, y *Scalar) { fiatScMontSub(&z.i, &x.i, &y.i) } 31 func (z *Scalar) Mul(x, y *Scalar) { fiatScMontMul(&z.i, &x.i, &y.i) } 32 func (z *Scalar) Sqr(x *Scalar) { fiatScMontSquare(&z.i, &x.i) } 33 func (z *Scalar) Inv(x *Scalar) { z.expVarTime(x, scOrderMinus2[:]) } 34 func (z *Scalar) toMont(in *scRaw) { fiatScMontMul(&z.i, in, &scRSquare) } 35 func (z Scalar) fromMont() (out scRaw) { fiatScMontMul(&out, &z.i, &scMont{1}); return } 36 37 // ScalarOrder is the order of the scalar field of the pairing groups, order is 38 // returned as a big-endian slice. 39 // 40 // ScalarOrder = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 41 func ScalarOrder() []byte { o := scOrder; return o[:] } 42 43 // exp calculates z=x^n, where n is in big-endian order. 44 func (z *Scalar) expVarTime(x *Scalar, n []byte) { 45 zz := new(Scalar) 46 zz.SetOne() 47 N := 8 * len(n) 48 for i := 0; i < N; i++ { 49 zz.Sqr(zz) 50 bit := 0x1 & (n[i/8] >> uint(7-i%8)) 51 if bit != 0 { 52 zz.Mul(zz, x) 53 } 54 } 55 z.Set(zz) 56 } 57 58 // SetBytes assigns to z the number modulo ScalarOrder stored in the slice 59 // (in big-endian order). 60 func (z *Scalar) SetBytes(data []byte) { 61 in64 := setBytesUnbounded(data, scOrder[:]) 62 s := &scRaw{} 63 copy(s[:], in64[:ScalarSize/8]) 64 z.toMont(s) 65 } 66 67 // MarshalBinary returns a slice of ScalarSize bytes that contains the minimal 68 // residue of z such that 0 <= z < ScalarOrder (in big-endian order). 69 func (z *Scalar) MarshalBinary() ([]byte, error) { 70 x := z.fromMont() 71 return conv.Uint64Le2BytesBe(x[:]), nil 72 } 73 74 // UnmarshalBinary reconstructs a Scalar from a slice that must have at least 75 // ScalarSize bytes and contain a number (in big-endian order) from 0 76 // to ScalarOrder-1. 77 func (z *Scalar) UnmarshalBinary(data []byte) error { 78 if len(data) < ScalarSize { 79 return errInputLength 80 } 81 in64, err := setBytesBounded(data[:ScalarSize], scOrder[:]) 82 if err == nil { 83 s := &scRaw{} 84 copy(s[:], in64[:ScalarSize/8]) 85 z.toMont(s) 86 } 87 return err 88 } 89 90 // SetString reconstructs a Fp from a numeric string from 0 to ScalarOrder-1. 91 func (z *Scalar) SetString(s string) error { 92 in64, err := setString(s, scOrder[:]) 93 if err == nil { 94 s := &scRaw{} 95 copy(s[:], in64[:ScalarSize/8]) 96 z.toMont(s) 97 } 98 return err 99 } 100 101 func fiatScMontCmovznzU64(z *uint64, b, x, y uint64) { cselectU64(z, b, x, y) } 102 103 var ( 104 // scOrder is the order of the Scalar field (big-endian). 105 scOrder = [ScalarSize]byte{ 106 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 107 0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, 0xd8, 0x05, 108 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, 109 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 110 } 111 // scOrderMinus2 is the scOrder minus two used for inversion (big-endian). 112 scOrderMinus2 = [ScalarSize]byte{ 113 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 114 0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, 0xd8, 0x05, 115 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, 116 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 117 } 118 // scRSquare is R^2 mod scOrder, where R=2^256 (little-endian). 119 scRSquare = scMont{ 120 0xc999e990f3f29c6d, 0x2b6cedcb87925c23, 121 0x05d314967254398f, 0x0748d9d99f59ff11, 122 } 123 )