1
2 package eddilithium2
3
4 import (
5 "crypto"
6 cryptoRand "crypto/rand"
7 "errors"
8 "io"
9
10 "github.com/cloudflare/circl/internal/sha3"
11 "github.com/cloudflare/circl/sign"
12 "github.com/cloudflare/circl/sign/dilithium/mode2"
13 "github.com/cloudflare/circl/sign/ed25519"
14 )
15
16 const (
17
18 SeedSize = mode2.SeedSize
19
20
21 PublicKeySize = mode2.PublicKeySize + ed25519.PublicKeySize
22
23
24 PrivateKeySize = mode2.PrivateKeySize + ed25519.SeedSize
25
26
27 SignatureSize = mode2.SignatureSize + ed25519.SignatureSize
28 )
29
30
31 type PublicKey struct {
32 e ed25519.PublicKey
33 d mode2.PublicKey
34 }
35
36
37 type PrivateKey struct {
38 e ed25519.PrivateKey
39 d mode2.PrivateKey
40 }
41
42
43
44 func GenerateKey(rand io.Reader) (*PublicKey, *PrivateKey, error) {
45 var seed [SeedSize]byte
46 if rand == nil {
47 rand = cryptoRand.Reader
48 }
49 _, err := io.ReadFull(rand, seed[:])
50 if err != nil {
51 return nil, nil, err
52 }
53
54 pk, sk := NewKeyFromSeed(&seed)
55 return pk, sk, nil
56 }
57
58
59 func NewKeyFromSeed(seed *[SeedSize]byte) (*PublicKey, *PrivateKey) {
60 var seed1 [32]byte
61 var seed2 [ed25519.SeedSize]byte
62
63
64
65
66
67
68
69
70 h := sha3.NewShake256()
71 _, _ = h.Write(seed[:])
72 _, _ = h.Read(seed1[:])
73 _, _ = h.Read(seed2[:])
74 dpk, dsk := mode2.NewKeyFromSeed(&seed1)
75 esk := ed25519.NewKeyFromSeed(seed2[:])
76
77 return &PublicKey{esk.Public().(ed25519.PublicKey), *dpk}, &PrivateKey{esk, *dsk}
78 }
79
80
81
82 func SignTo(sk *PrivateKey, msg []byte, signature []byte) {
83 mode2.SignTo(
84 &sk.d,
85 msg,
86 signature[:mode2.SignatureSize],
87 )
88 esig := ed25519.Sign(
89 sk.e,
90 msg,
91 )
92 copy(signature[mode2.SignatureSize:], esig[:])
93 }
94
95
96 func Verify(pk *PublicKey, msg []byte, signature []byte) bool {
97 if !mode2.Verify(
98 &pk.d,
99 msg,
100 signature[:mode2.SignatureSize],
101 ) {
102 return false
103 }
104 if !ed25519.Verify(
105 pk.e,
106 msg,
107 signature[mode2.SignatureSize:],
108 ) {
109 return false
110 }
111 return true
112 }
113
114
115 func (pk *PublicKey) Unpack(buf *[PublicKeySize]byte) {
116 var tmp [mode2.PublicKeySize]byte
117 copy(tmp[:], buf[:mode2.PublicKeySize])
118 pk.d.Unpack(&tmp)
119 pk.e = make([]byte, ed25519.PublicKeySize)
120 copy(pk.e, buf[mode2.PublicKeySize:])
121 }
122
123
124 func (sk *PrivateKey) Unpack(buf *[PrivateKeySize]byte) {
125 var tmp [mode2.PrivateKeySize]byte
126 copy(tmp[:], buf[:mode2.PrivateKeySize])
127 sk.d.Unpack(&tmp)
128 sk.e = ed25519.NewKeyFromSeed(buf[mode2.PrivateKeySize:])
129 }
130
131
132 func (pk *PublicKey) Pack(buf *[PublicKeySize]byte) {
133 var tmp [mode2.PublicKeySize]byte
134 pk.d.Pack(&tmp)
135 copy(buf[:mode2.PublicKeySize], tmp[:])
136 copy(buf[mode2.PublicKeySize:], pk.e)
137 }
138
139
140 func (sk *PrivateKey) Pack(buf *[PrivateKeySize]byte) {
141 var tmp [mode2.PrivateKeySize]byte
142 sk.d.Pack(&tmp)
143 copy(buf[:mode2.PrivateKeySize], tmp[:])
144 copy(buf[mode2.PrivateKeySize:], sk.e.Seed())
145 }
146
147
148 func (pk *PublicKey) Bytes() []byte {
149 return append(pk.d.Bytes(), pk.e...)
150 }
151
152
153 func (sk *PrivateKey) Bytes() []byte {
154 return append(sk.d.Bytes(), sk.e.Seed()...)
155 }
156
157
158 func (pk *PublicKey) MarshalBinary() ([]byte, error) {
159 return pk.Bytes(), nil
160 }
161
162
163 func (sk *PrivateKey) MarshalBinary() ([]byte, error) {
164 return sk.Bytes(), nil
165 }
166
167
168 func (pk *PublicKey) UnmarshalBinary(data []byte) error {
169 if len(data) != PublicKeySize {
170 return errors.New("packed public key must be of eddilithium2.PublicKeySize bytes")
171 }
172 var buf [PublicKeySize]byte
173 copy(buf[:], data)
174 pk.Unpack(&buf)
175 return nil
176 }
177
178
179 func (sk *PrivateKey) UnmarshalBinary(data []byte) error {
180 if len(data) != PrivateKeySize {
181 return errors.New("packed private key must be of eddilithium2.PrivateKeySize bytes")
182 }
183 var buf [PrivateKeySize]byte
184 copy(buf[:], data)
185 sk.Unpack(&buf)
186 return nil
187 }
188
189 func (sk *PrivateKey) Scheme() sign.Scheme { return sch }
190 func (pk *PublicKey) Scheme() sign.Scheme { return sch }
191
192 func (sk *PrivateKey) Equal(other crypto.PrivateKey) bool {
193 castOther, ok := other.(*PrivateKey)
194 if !ok {
195 return false
196 }
197 return castOther.e.Equal(sk.e) && castOther.d.Equal(&sk.d)
198 }
199
200 func (pk *PublicKey) Equal(other crypto.PublicKey) bool {
201 castOther, ok := other.(*PublicKey)
202 if !ok {
203 return false
204 }
205 return castOther.e.Equal(pk.e) && castOther.d.Equal(&pk.d)
206 }
207
208
209
210
211
212
213
214
215
216
217 func (sk *PrivateKey) Sign(
218 rand io.Reader, msg []byte, opts crypto.SignerOpts,
219 ) (signature []byte, err error) {
220 var sig [SignatureSize]byte
221
222 if opts.HashFunc() != crypto.Hash(0) {
223 return nil, errors.New("eddilithium2: cannot sign hashed message")
224 }
225
226 SignTo(sk, msg, sig[:])
227 return sig[:], nil
228 }
229
230
231
232
233
234 func (sk *PrivateKey) Public() crypto.PublicKey {
235 return &PublicKey{
236 sk.e.Public().(ed25519.PublicKey),
237 *sk.d.Public().(*mode2.PublicKey),
238 }
239 }
240
View as plain text