1
2
3
4
5
6
7
8
9
10 package sikep503
11
12 import (
13 "bytes"
14 cryptoRand "crypto/rand"
15 "crypto/subtle"
16 "io"
17
18 "github.com/cloudflare/circl/dh/sidh"
19 "github.com/cloudflare/circl/internal/sha3"
20 "github.com/cloudflare/circl/kem"
21 )
22
23
24 type PrivateKey struct {
25 sk *sidh.PrivateKey
26 pk *sidh.PublicKey
27 }
28
29
30 type PublicKey sidh.PublicKey
31
32 const (
33 SeedSize = 32
34 EncapsulationSeedSize = 32
35 )
36
37 type scheme struct{}
38
39 var sch kem.Scheme = &scheme{}
40
41
42
43
44 func Scheme() kem.Scheme { return sch }
45
46 var params *sidh.KEM
47
48 func (*scheme) Name() string { return "SIKEp503" }
49 func (*scheme) PublicKeySize() int { return params.PublicKeySize() }
50 func (*scheme) PrivateKeySize() int { return params.PrivateKeySize() }
51 func (*scheme) SeedSize() int { return SeedSize }
52 func (*scheme) SharedKeySize() int { return params.SharedSecretSize() }
53 func (*scheme) CiphertextSize() int { return params.CiphertextSize() }
54 func (*scheme) EncapsulationSeedSize() int { return EncapsulationSeedSize }
55
56 func (sk *PrivateKey) Scheme() kem.Scheme { return sch }
57 func (pk *PublicKey) Scheme() kem.Scheme { return sch }
58
59 func (sk *PrivateKey) MarshalBinary() ([]byte, error) {
60 ret := make([]byte, sk.sk.Size())
61 sk.sk.Export(ret)
62 return ret, nil
63 }
64
65 func (sk *PrivateKey) Equal(other kem.PrivateKey) bool {
66 oth, ok := other.(*PrivateKey)
67 if !ok {
68 return false
69 }
70 a, _ := sk.MarshalBinary()
71 b, _ := oth.MarshalBinary()
72 return subtle.ConstantTimeCompare(a, b) == 1
73 }
74
75 func (sk *PrivateKey) Public() kem.PublicKey {
76 if sk.pk == nil {
77 sk.pk = sidh.NewPublicKey(sidh.Fp503, sidh.KeyVariantSike)
78 sk.sk.GeneratePublicKey(sk.pk)
79 }
80 return (*PublicKey)(sk.pk)
81 }
82
83 func (pk *PublicKey) Equal(other kem.PublicKey) bool {
84 oth, ok := other.(*PublicKey)
85 if !ok {
86 return false
87 }
88 a, _ := pk.MarshalBinary()
89 b, _ := oth.MarshalBinary()
90 return bytes.Equal(a, b)
91 }
92
93 func (pk *PublicKey) MarshalBinary() ([]byte, error) {
94 cpk := (*sidh.PublicKey)(pk)
95 ret := make([]byte, cpk.Size())
96 cpk.Export(ret)
97 return ret, nil
98 }
99
100
101 func GenerateKeyPair(rand io.Reader) (kem.PublicKey, kem.PrivateKey, error) {
102 sk := sidh.NewPrivateKey(sidh.Fp503, sidh.KeyVariantSike)
103
104 if err := sk.Generate(rand); err != nil {
105 return nil, nil, err
106 }
107 priv := &PrivateKey{sk: sk}
108
109 return priv.Public(), priv, nil
110 }
111
112 func (*scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) {
113 return GenerateKeyPair(cryptoRand.Reader)
114 }
115
116 func (*scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) {
117 if len(seed) != SeedSize {
118 panic(kem.ErrSeedSize)
119 }
120 h := sha3.NewShake256()
121 _, _ = h.Write(seed[:])
122 pk, sk, err := GenerateKeyPair(&h)
123
124 if err != nil {
125 panic(err)
126 }
127
128 return pk, sk
129 }
130
131 func (sch *scheme) Encapsulate(pk kem.PublicKey) (ct []byte, ss []byte, err error) {
132 var seed [EncapsulationSeedSize]byte
133 if _, err := cryptoRand.Read(seed[:]); err != nil {
134 return nil, nil, err
135 }
136 return sch.EncapsulateDeterministically(pk, seed[:])
137 }
138
139 func (sch *scheme) EncapsulateDeterministically(pk kem.PublicKey, seed []byte) (ct []byte, ss []byte, err error) {
140 if len(seed) != EncapsulationSeedSize {
141 return nil, nil, kem.ErrSeedSize
142 }
143
144 pub, ok := pk.(*PublicKey)
145 if !ok {
146 return nil, nil, kem.ErrTypeMismatch
147 }
148
149 ct = make([]byte, sch.CiphertextSize())
150 ss = make([]byte, sch.SharedKeySize())
151
152 h := sha3.NewShake256()
153 _, _ = h.Write(seed[:])
154 ctx := sidh.NewSike503(&h)
155
156 if err := ctx.Encapsulate(ct, ss, (*sidh.PublicKey)(pub)); err != nil {
157 return nil, nil, err
158 }
159 return ct, ss, nil
160 }
161
162 func (sch *scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) {
163 if len(ct) != sch.CiphertextSize() {
164 return nil, kem.ErrCiphertextSize
165 }
166
167 priv, ok := sk.(*PrivateKey)
168 if !ok {
169 return nil, kem.ErrTypeMismatch
170 }
171
172 sikePub := sidh.NewPublicKey(sidh.Fp503, sidh.KeyVariantSike)
173 priv.sk.GeneratePublicKey(sikePub)
174
175 ss := make([]byte, sch.SharedKeySize())
176
177 ctx := sidh.NewSike503(nil)
178 if err := ctx.Decapsulate(ss, priv.sk, sikePub, ct); err != nil {
179 return nil, err
180 }
181
182 return ss, nil
183 }
184
185 func (sch *scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) {
186 if len(buf) != sch.PublicKeySize() {
187 return nil, kem.ErrPubKeySize
188 }
189 pk := sidh.NewPublicKey(sidh.Fp503, sidh.KeyVariantSike)
190 if err := pk.Import(buf); err != nil {
191 return nil, err
192 }
193 return (*PublicKey)(pk), nil
194 }
195
196 func (sch *scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) {
197 if len(buf) != sch.PrivateKeySize() {
198 return nil, kem.ErrPrivKeySize
199 }
200 sk := sidh.NewPrivateKey(sidh.Fp503, sidh.KeyVariantSike)
201 if err := sk.Import(buf); err != nil {
202 return nil, err
203 }
204 return &PrivateKey{sk: sk}, nil
205 }
206
207 func init() {
208 params = sidh.NewSike503(nil)
209 }
210
View as plain text