github.com/cloudflare/circl@v1.5.0/math/mlsbset/mlsbset.go (about)

     1  // Package mlsbset provides a constant-time exponentiation method with precomputation.
     2  //
     3  // References: "Efficient and secure algorithms for GLV-based scalar
     4  // multiplication and their implementation on GLV–GLS curves" by (Faz-Hernandez et al.)
     5  //   - https://doi.org/10.1007/s13389-014-0085-7
     6  //   - https://eprint.iacr.org/2013/158
     7  package mlsbset
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"math/big"
    13  
    14  	"github.com/cloudflare/circl/internal/conv"
    15  )
    16  
    17  // EltG is a group element.
    18  type EltG interface{}
    19  
    20  // EltP is a precomputed group element.
    21  type EltP interface{}
    22  
    23  // Group defines the operations required by MLSBSet exponentiation method.
    24  type Group interface {
    25  	Identity() EltG                    // Returns the identity of the group.
    26  	Sqr(x EltG)                        // Calculates x = x^2.
    27  	Mul(x EltG, y EltP)                // Calculates x = x*y.
    28  	NewEltP() EltP                     // Returns an arbitrary precomputed element.
    29  	ExtendedEltP() EltP                // Returns the precomputed element x^(2^(w*d)).
    30  	Lookup(a EltP, v uint, s, u int32) // Sets a = s*T[v][u].
    31  }
    32  
    33  // Params contains the parameters of the encoding.
    34  type Params struct {
    35  	T uint // T is the maximum size (in bits) of exponents.
    36  	V uint // V is the number of tables.
    37  	W uint // W is the window size.
    38  	E uint // E is the number of digits per table.
    39  	D uint // D is the number of digits in total.
    40  	L uint // L is the length of the code.
    41  }
    42  
    43  // Encoder allows to convert integers into valid powers.
    44  type Encoder struct{ p Params }
    45  
    46  // New produces an encoder of the MLSBSet algorithm.
    47  func New(t, v, w uint) (Encoder, error) {
    48  	if !(t > 1 && v >= 1 && w >= 2) {
    49  		return Encoder{}, errors.New("t>1, v>=1, w>=2")
    50  	}
    51  	e := (t + w*v - 1) / (w * v)
    52  	d := e * v
    53  	l := d * w
    54  	return Encoder{Params{t, v, w, e, d, l}}, nil
    55  }
    56  
    57  // Encode converts an odd integer k into a valid power for exponentiation.
    58  func (m Encoder) Encode(k []byte) (*Power, error) {
    59  	if len(k) == 0 {
    60  		return nil, errors.New("empty slice")
    61  	}
    62  	if !(len(k) <= int(m.p.L+7)>>3) {
    63  		return nil, errors.New("k too big")
    64  	}
    65  	if k[0]%2 == 0 {
    66  		return nil, errors.New("k must be odd")
    67  	}
    68  	ap := int((m.p.L+7)/8) - len(k)
    69  	k = append(k, make([]byte, ap)...)
    70  	s := m.signs(k)
    71  	b := make([]int32, m.p.L-m.p.D)
    72  	c := conv.BytesLe2BigInt(k)
    73  	c.Rsh(c, m.p.D)
    74  	var bi big.Int
    75  	for i := m.p.D; i < m.p.L; i++ {
    76  		c0 := int32(c.Bit(0))
    77  		b[i-m.p.D] = s[i%m.p.D] * c0
    78  		bi.SetInt64(int64(b[i-m.p.D] >> 1))
    79  		c.Rsh(c, 1)
    80  		c.Sub(c, &bi)
    81  	}
    82  	carry := int(c.Int64())
    83  	return &Power{m, s, b, carry}, nil
    84  }
    85  
    86  // signs calculates the set of signs.
    87  func (m Encoder) signs(k []byte) []int32 {
    88  	s := make([]int32, m.p.D)
    89  	s[m.p.D-1] = 1
    90  	for i := uint(1); i < m.p.D; i++ {
    91  		ki := int32((k[i>>3] >> (i & 0x7)) & 0x1)
    92  		s[i-1] = 2*ki - 1
    93  	}
    94  	return s
    95  }
    96  
    97  // GetParams returns the complementary parameters of the encoding.
    98  func (m Encoder) GetParams() Params { return m.p }
    99  
   100  // tableSize returns the size of each table.
   101  func (m Encoder) tableSize() uint { return 1 << (m.p.W - 1) }
   102  
   103  // Elts returns the total number of elements that must be precomputed.
   104  func (m Encoder) Elts() uint { return m.p.V * m.tableSize() }
   105  
   106  // IsExtended returns true if the element x^(2^(wd)) must be calculated.
   107  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 }
   108  
   109  // Ops returns the number of squares and multiplications executed during an exponentiation.
   110  func (m Encoder) Ops() (S uint, M uint) {
   111  	S = m.p.E
   112  	M = m.p.E * m.p.V
   113  	if m.IsExtended() {
   114  		M++
   115  	}
   116  	return
   117  }
   118  
   119  func (m Encoder) String() string {
   120  	return fmt.Sprintf("T: %v W: %v V: %v e: %v d: %v l: %v wv|t: %v",
   121  		m.p.T, m.p.W, m.p.V, m.p.E, m.p.D, m.p.L, m.IsExtended())
   122  }