1 package dns
2
3 import (
4 "bufio"
5 "crypto"
6 "crypto/ecdsa"
7 "crypto/ed25519"
8 "crypto/rsa"
9 "io"
10 "math/big"
11 "strconv"
12 "strings"
13 )
14
15
16
17 func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
18 if s == "" || s[len(s)-1] != '\n' {
19 return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
20 }
21 return k.ReadPrivateKey(strings.NewReader(s), "")
22 }
23
24
25
26
27
28 func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
29 m, err := parseKey(q, file)
30 if m == nil {
31 return nil, err
32 }
33 if _, ok := m["private-key-format"]; !ok {
34 return nil, ErrPrivKey
35 }
36 if m["private-key-format"] != "v1.2" && m["private-key-format"] != "v1.3" {
37 return nil, ErrPrivKey
38 }
39
40 algoStr, _, _ := strings.Cut(m["algorithm"], " ")
41 algo, err := strconv.ParseUint(algoStr, 10, 8)
42 if err != nil {
43 return nil, ErrPrivKey
44 }
45 switch uint8(algo) {
46 case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
47 priv, err := readPrivateKeyRSA(m)
48 if err != nil {
49 return nil, err
50 }
51 pub := k.publicKeyRSA()
52 if pub == nil {
53 return nil, ErrKey
54 }
55 priv.PublicKey = *pub
56 return priv, nil
57 case ECDSAP256SHA256, ECDSAP384SHA384:
58 priv, err := readPrivateKeyECDSA(m)
59 if err != nil {
60 return nil, err
61 }
62 pub := k.publicKeyECDSA()
63 if pub == nil {
64 return nil, ErrKey
65 }
66 priv.PublicKey = *pub
67 return priv, nil
68 case ED25519:
69 return readPrivateKeyED25519(m)
70 default:
71 return nil, ErrAlg
72 }
73 }
74
75
76 func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
77 p := new(rsa.PrivateKey)
78 p.Primes = []*big.Int{nil, nil}
79 for k, v := range m {
80 switch k {
81 case "modulus", "publicexponent", "privateexponent", "prime1", "prime2":
82 v1, err := fromBase64([]byte(v))
83 if err != nil {
84 return nil, err
85 }
86 switch k {
87 case "modulus":
88 p.PublicKey.N = new(big.Int).SetBytes(v1)
89 case "publicexponent":
90 i := new(big.Int).SetBytes(v1)
91 p.PublicKey.E = int(i.Int64())
92 case "privateexponent":
93 p.D = new(big.Int).SetBytes(v1)
94 case "prime1":
95 p.Primes[0] = new(big.Int).SetBytes(v1)
96 case "prime2":
97 p.Primes[1] = new(big.Int).SetBytes(v1)
98 }
99 case "exponent1", "exponent2", "coefficient":
100
101 case "created", "publish", "activate":
102
103 }
104 }
105 return p, nil
106 }
107
108 func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
109 p := new(ecdsa.PrivateKey)
110 p.D = new(big.Int)
111
112 for k, v := range m {
113 switch k {
114 case "privatekey":
115 v1, err := fromBase64([]byte(v))
116 if err != nil {
117 return nil, err
118 }
119 p.D.SetBytes(v1)
120 case "created", "publish", "activate":
121
122 }
123 }
124 return p, nil
125 }
126
127 func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
128 var p ed25519.PrivateKey
129
130 for k, v := range m {
131 switch k {
132 case "privatekey":
133 p1, err := fromBase64([]byte(v))
134 if err != nil {
135 return nil, err
136 }
137 if len(p1) != ed25519.SeedSize {
138 return nil, ErrPrivKey
139 }
140 p = ed25519.NewKeyFromSeed(p1)
141 case "created", "publish", "activate":
142
143 }
144 }
145 return p, nil
146 }
147
148
149
150 func parseKey(r io.Reader, file string) (map[string]string, error) {
151 m := make(map[string]string)
152 var k string
153
154 c := newKLexer(r)
155
156 for l, ok := c.Next(); ok; l, ok = c.Next() {
157
158 switch l.value {
159 case zKey:
160 k = l.token
161 case zValue:
162 if k == "" {
163 return nil, &ParseError{file, "no private key seen", l}
164 }
165
166 m[strings.ToLower(k)] = l.token
167 k = ""
168 }
169 }
170
171
172 if err := c.Err(); err != nil {
173 return nil, &ParseError{file: file, err: err.Error()}
174 }
175
176 return m, nil
177 }
178
179 type klexer struct {
180 br io.ByteReader
181
182 readErr error
183
184 line int
185 column int
186
187 key bool
188
189 eol bool
190 }
191
192 func newKLexer(r io.Reader) *klexer {
193 br, ok := r.(io.ByteReader)
194 if !ok {
195 br = bufio.NewReaderSize(r, 1024)
196 }
197
198 return &klexer{
199 br: br,
200
201 line: 1,
202
203 key: true,
204 }
205 }
206
207 func (kl *klexer) Err() error {
208 if kl.readErr == io.EOF {
209 return nil
210 }
211
212 return kl.readErr
213 }
214
215
216 func (kl *klexer) readByte() (byte, bool) {
217 if kl.readErr != nil {
218 return 0, false
219 }
220
221 c, err := kl.br.ReadByte()
222 if err != nil {
223 kl.readErr = err
224 return 0, false
225 }
226
227
228
229 if kl.eol {
230 kl.line++
231 kl.column = 0
232 kl.eol = false
233 }
234
235 if c == '\n' {
236 kl.eol = true
237 } else {
238 kl.column++
239 }
240
241 return c, true
242 }
243
244 func (kl *klexer) Next() (lex, bool) {
245 var (
246 l lex
247
248 str strings.Builder
249
250 commt bool
251 )
252
253 for x, ok := kl.readByte(); ok; x, ok = kl.readByte() {
254 l.line, l.column = kl.line, kl.column
255
256 switch x {
257 case ':':
258 if commt || !kl.key {
259 break
260 }
261
262 kl.key = false
263
264
265 kl.readByte()
266
267 l.value = zKey
268 l.token = str.String()
269 return l, true
270 case ';':
271 commt = true
272 case '\n':
273 if commt {
274
275 commt = false
276 }
277
278 if kl.key && str.Len() == 0 {
279
280 break
281 }
282
283 kl.key = true
284
285 l.value = zValue
286 l.token = str.String()
287 return l, true
288 default:
289 if commt {
290 break
291 }
292
293 str.WriteByte(x)
294 }
295 }
296
297 if kl.readErr != nil && kl.readErr != io.EOF {
298
299 return lex{value: zEOF}, false
300 }
301
302 if str.Len() > 0 {
303
304 l.value = zValue
305 l.token = str.String()
306 return l, true
307 }
308
309 return lex{value: zEOF}, false
310 }
311
View as plain text