...
1
2
3
4
5
6
7 package mlsbset
8
9 import (
10 "errors"
11 "fmt"
12 "math/big"
13
14 "github.com/cloudflare/circl/internal/conv"
15 )
16
17
18 type EltG interface{}
19
20
21 type EltP interface{}
22
23
24 type Group interface {
25 Identity() EltG
26 Sqr(x EltG)
27 Mul(x EltG, y EltP)
28 NewEltP() EltP
29 ExtendedEltP() EltP
30 Lookup(a EltP, v uint, s, u int32)
31 }
32
33
34 type Params struct {
35 T uint
36 V uint
37 W uint
38 E uint
39 D uint
40 L uint
41 }
42
43
44 type Encoder struct{ p Params }
45
46
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
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
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
98 func (m Encoder) GetParams() Params { return m.p }
99
100
101 func (m Encoder) tableSize() uint { return 1 << (m.p.W - 1) }
102
103
104 func (m Encoder) Elts() uint { return m.p.V * m.tableSize() }
105
106
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
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 }
123
View as plain text