Files
zeekay cc986c328d lux/kms: orphan history at f2e793bf8 (was: kms: wire luxfi/mpc as REK backend)
Squashes all pre-rewrite history into a single root commit. Previous tree:
- 14506 commits including upstream Infisical fork history
- Multiple merge chains carrying pre-purge content

Force-rewrite per disk-space reclamation discipline. GHCR images
(1.9.9, 1.9.11) remain immutable; their git lineage is no longer
materialized.
2026-06-07 14:28:09 -07:00

124 lines
4.2 KiB
Go

package ff
import (
"io"
"github.com/cloudflare/circl/internal/conv"
)
// ScalarSize is the length in bytes of a Scalar.
const ScalarSize = 32
// scMont represents an element in the Montgomery domain (little-endian).
type scMont = [ScalarSize / 8]uint64
// scRaw represents a scalar in the integers domain (little-endian).
type scRaw = [ScalarSize / 8]uint64
// Scalar represents positive integers less than ScalarOrder.
type Scalar struct{ i scMont }
func (z Scalar) String() string { x := z.fromMont(); return conv.Uint64Le2Hex(x[:]) }
func (z *Scalar) Set(x *Scalar) { z.i = x.i }
func (z *Scalar) SetUint64(n uint64) { z.toMont(&scRaw{n}) }
func (z *Scalar) SetOne() { z.SetUint64(1) }
func (z *Scalar) Random(r io.Reader) error { return randomInt(z.i[:], r, scOrder[:]) }
func (z Scalar) IsZero() int { return ctUint64Eq(z.i[:], (&scMont{})[:]) }
func (z Scalar) IsEqual(x *Scalar) int { return ctUint64Eq(z.i[:], x.i[:]) }
func (z *Scalar) Neg() { fiatScMontSub(&z.i, &scMont{}, &z.i) }
func (z *Scalar) Add(x, y *Scalar) { fiatScMontAdd(&z.i, &x.i, &y.i) }
func (z *Scalar) Sub(x, y *Scalar) { fiatScMontSub(&z.i, &x.i, &y.i) }
func (z *Scalar) Mul(x, y *Scalar) { fiatScMontMul(&z.i, &x.i, &y.i) }
func (z *Scalar) Sqr(x *Scalar) { fiatScMontSquare(&z.i, &x.i) }
func (z *Scalar) Inv(x *Scalar) { z.expVarTime(x, scOrderMinus2[:]) }
func (z *Scalar) toMont(in *scRaw) { fiatScMontMul(&z.i, in, &scRSquare) }
func (z Scalar) fromMont() (out scRaw) { fiatScMontMul(&out, &z.i, &scMont{1}); return }
// ScalarOrder is the order of the scalar field of the pairing groups, order is
// returned as a big-endian slice.
//
// ScalarOrder = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
func ScalarOrder() []byte { o := scOrder; return o[:] }
// exp calculates z=x^n, where n is in big-endian order.
func (z *Scalar) expVarTime(x *Scalar, n []byte) {
zz := new(Scalar)
zz.SetOne()
N := 8 * len(n)
for i := 0; i < N; i++ {
zz.Sqr(zz)
bit := 0x1 & (n[i/8] >> uint(7-i%8))
if bit != 0 {
zz.Mul(zz, x)
}
}
z.Set(zz)
}
// SetBytes assigns to z the number modulo ScalarOrder stored in the slice
// (in big-endian order).
func (z *Scalar) SetBytes(data []byte) {
in64 := setBytesUnbounded(data, scOrder[:])
s := &scRaw{}
copy(s[:], in64[:ScalarSize/8])
z.toMont(s)
}
// MarshalBinary returns a slice of ScalarSize bytes that contains the minimal
// residue of z such that 0 <= z < ScalarOrder (in big-endian order).
func (z *Scalar) MarshalBinary() ([]byte, error) {
x := z.fromMont()
return conv.Uint64Le2BytesBe(x[:]), nil
}
// UnmarshalBinary reconstructs a Scalar from a slice that must have at least
// ScalarSize bytes and contain a number (in big-endian order) from 0
// to ScalarOrder-1.
func (z *Scalar) UnmarshalBinary(data []byte) error {
if len(data) < ScalarSize {
return errInputLength
}
in64, err := setBytesBounded(data[:ScalarSize], scOrder[:])
if err == nil {
s := &scRaw{}
copy(s[:], in64[:ScalarSize/8])
z.toMont(s)
}
return err
}
// SetString reconstructs a Fp from a numeric string from 0 to ScalarOrder-1.
func (z *Scalar) SetString(s string) error {
in64, err := setString(s, scOrder[:])
if err == nil {
s := &scRaw{}
copy(s[:], in64[:ScalarSize/8])
z.toMont(s)
}
return err
}
func fiatScMontCmovznzU64(z *uint64, b, x, y uint64) { cselectU64(z, b, x, y) }
var (
// scOrder is the order of the Scalar field (big-endian).
scOrder = [ScalarSize]byte{
0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48,
0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, 0xd8, 0x05,
0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
}
// scOrderMinus2 is the scOrder minus two used for inversion (big-endian).
scOrderMinus2 = [ScalarSize]byte{
0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48,
0x33, 0x39, 0xd8, 0x08, 0x09, 0xa1, 0xd8, 0x05,
0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe,
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
}
// scRSquare is R^2 mod scOrder, where R=2^256 (little-endian).
scRSquare = scMont{
0xc999e990f3f29c6d, 0x2b6cedcb87925c23,
0x05d314967254398f, 0x0748d9d99f59ff11,
}
)