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