cheat/vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go
Christopher Allen Lane 95a4e31b6c chore(deps): upgrade dependencies
Upgrade all dependencies to newest versions.
2023-12-13 08:29:02 -05:00

123 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package mlsbset provides a constant-time exponentiation method with precomputation.
//
// References: "Efficient and secure algorithms for GLV-based scalar
// multiplication and their implementation on GLVGLS curves" by (Faz-Hernandez et al.)
// - https://doi.org/10.1007/s13389-014-0085-7
// - https://eprint.iacr.org/2013/158
package mlsbset
import (
"errors"
"fmt"
"math/big"
"github.com/cloudflare/circl/internal/conv"
)
// EltG is a group element.
type EltG interface{}
// EltP is a precomputed group element.
type EltP interface{}
// Group defines the operations required by MLSBSet exponentiation method.
type Group interface {
Identity() EltG // Returns the identity of the group.
Sqr(x EltG) // Calculates x = x^2.
Mul(x EltG, y EltP) // Calculates x = x*y.
NewEltP() EltP // Returns an arbitrary precomputed element.
ExtendedEltP() EltP // Returns the precomputed element x^(2^(w*d)).
Lookup(a EltP, v uint, s, u int32) // Sets a = s*T[v][u].
}
// Params contains the parameters of the encoding.
type Params struct {
T uint // T is the maximum size (in bits) of exponents.
V uint // V is the number of tables.
W uint // W is the window size.
E uint // E is the number of digits per table.
D uint // D is the number of digits in total.
L uint // L is the length of the code.
}
// Encoder allows to convert integers into valid powers.
type Encoder struct{ p Params }
// New produces an encoder of the MLSBSet algorithm.
func New(t, v, w uint) (Encoder, error) {
if !(t > 1 && v >= 1 && w >= 2) {
return Encoder{}, errors.New("t>1, v>=1, w>=2")
}
e := (t + w*v - 1) / (w * v)
d := e * v
l := d * w
return Encoder{Params{t, v, w, e, d, l}}, nil
}
// Encode converts an odd integer k into a valid power for exponentiation.
func (m Encoder) Encode(k []byte) (*Power, error) {
if len(k) == 0 {
return nil, errors.New("empty slice")
}
if !(len(k) <= int(m.p.L+7)>>3) {
return nil, errors.New("k too big")
}
if k[0]%2 == 0 {
return nil, errors.New("k must be odd")
}
ap := int((m.p.L+7)/8) - len(k)
k = append(k, make([]byte, ap)...)
s := m.signs(k)
b := make([]int32, m.p.L-m.p.D)
c := conv.BytesLe2BigInt(k)
c.Rsh(c, m.p.D)
var bi big.Int
for i := m.p.D; i < m.p.L; i++ {
c0 := int32(c.Bit(0))
b[i-m.p.D] = s[i%m.p.D] * c0
bi.SetInt64(int64(b[i-m.p.D] >> 1))
c.Rsh(c, 1)
c.Sub(c, &bi)
}
carry := int(c.Int64())
return &Power{m, s, b, carry}, nil
}
// signs calculates the set of signs.
func (m Encoder) signs(k []byte) []int32 {
s := make([]int32, m.p.D)
s[m.p.D-1] = 1
for i := uint(1); i < m.p.D; i++ {
ki := int32((k[i>>3] >> (i & 0x7)) & 0x1)
s[i-1] = 2*ki - 1
}
return s
}
// GetParams returns the complementary parameters of the encoding.
func (m Encoder) GetParams() Params { return m.p }
// tableSize returns the size of each table.
func (m Encoder) tableSize() uint { return 1 << (m.p.W - 1) }
// Elts returns the total number of elements that must be precomputed.
func (m Encoder) Elts() uint { return m.p.V * m.tableSize() }
// IsExtended returns true if the element x^(2^(wd)) must be calculated.
func (m Encoder) IsExtended() bool { q := m.p.T / (m.p.V * m.p.W); return m.p.T == q*m.p.V*m.p.W }
// Ops returns the number of squares and multiplications executed during an exponentiation.
func (m Encoder) Ops() (S uint, M uint) {
S = m.p.E
M = m.p.E * m.p.V
if m.IsExtended() {
M++
}
return
}
func (m Encoder) String() string {
return fmt.Sprintf("T: %v W: %v V: %v e: %v d: %v l: %v wv|t: %v",
m.p.T, m.p.W, m.p.V, m.p.E, m.p.D, m.p.L, m.IsExtended())
}