OSDN Git Service

rename (#465)
[bytom/vapor.git] / vendor / github.com / miekg / dns / dnssec_keyscan.go
1 package dns
2
3 import (
4         "bufio"
5         "bytes"
6         "crypto"
7         "crypto/dsa"
8         "crypto/ecdsa"
9         "crypto/rsa"
10         "io"
11         "math/big"
12         "strconv"
13         "strings"
14
15         "github.com/bytom/vapor/crypto/ed25519"
16 )
17
18 // NewPrivateKey returns a PrivateKey by parsing the string s.
19 // s should be in the same form of the BIND private key files.
20 func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
21         if s == "" || s[len(s)-1] != '\n' { // We need a closing newline
22                 return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
23         }
24         return k.ReadPrivateKey(strings.NewReader(s), "")
25 }
26
27 // ReadPrivateKey reads a private key from the io.Reader q. The string file is
28 // only used in error reporting.
29 // The public key must be known, because some cryptographic algorithms embed
30 // the public inside the privatekey.
31 func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
32         m, err := parseKey(q, file)
33         if m == nil {
34                 return nil, err
35         }
36         if _, ok := m["private-key-format"]; !ok {
37                 return nil, ErrPrivKey
38         }
39         if m["private-key-format"] != "v1.2" && m["private-key-format"] != "v1.3" {
40                 return nil, ErrPrivKey
41         }
42         // TODO(mg): check if the pubkey matches the private key
43         algo, err := strconv.ParseUint(strings.SplitN(m["algorithm"], " ", 2)[0], 10, 8)
44         if err != nil {
45                 return nil, ErrPrivKey
46         }
47         switch uint8(algo) {
48         case DSA:
49                 priv, err := readPrivateKeyDSA(m)
50                 if err != nil {
51                         return nil, err
52                 }
53                 pub := k.publicKeyDSA()
54                 if pub == nil {
55                         return nil, ErrKey
56                 }
57                 priv.PublicKey = *pub
58                 return priv, nil
59         case RSAMD5:
60                 fallthrough
61         case RSASHA1:
62                 fallthrough
63         case RSASHA1NSEC3SHA1:
64                 fallthrough
65         case RSASHA256:
66                 fallthrough
67         case RSASHA512:
68                 priv, err := readPrivateKeyRSA(m)
69                 if err != nil {
70                         return nil, err
71                 }
72                 pub := k.publicKeyRSA()
73                 if pub == nil {
74                         return nil, ErrKey
75                 }
76                 priv.PublicKey = *pub
77                 return priv, nil
78         case ECCGOST:
79                 return nil, ErrPrivKey
80         case ECDSAP256SHA256:
81                 fallthrough
82         case ECDSAP384SHA384:
83                 priv, err := readPrivateKeyECDSA(m)
84                 if err != nil {
85                         return nil, err
86                 }
87                 pub := k.publicKeyECDSA()
88                 if pub == nil {
89                         return nil, ErrKey
90                 }
91                 priv.PublicKey = *pub
92                 return priv, nil
93         case ED25519:
94                 return readPrivateKeyED25519(m)
95         default:
96                 return nil, ErrPrivKey
97         }
98 }
99
100 // Read a private key (file) string and create a public key. Return the private key.
101 func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
102         p := new(rsa.PrivateKey)
103         p.Primes = []*big.Int{nil, nil}
104         for k, v := range m {
105                 switch k {
106                 case "modulus", "publicexponent", "privateexponent", "prime1", "prime2":
107                         v1, err := fromBase64([]byte(v))
108                         if err != nil {
109                                 return nil, err
110                         }
111                         switch k {
112                         case "modulus":
113                                 p.PublicKey.N = big.NewInt(0)
114                                 p.PublicKey.N.SetBytes(v1)
115                         case "publicexponent":
116                                 i := big.NewInt(0)
117                                 i.SetBytes(v1)
118                                 p.PublicKey.E = int(i.Int64()) // int64 should be large enough
119                         case "privateexponent":
120                                 p.D = big.NewInt(0)
121                                 p.D.SetBytes(v1)
122                         case "prime1":
123                                 p.Primes[0] = big.NewInt(0)
124                                 p.Primes[0].SetBytes(v1)
125                         case "prime2":
126                                 p.Primes[1] = big.NewInt(0)
127                                 p.Primes[1].SetBytes(v1)
128                         }
129                 case "exponent1", "exponent2", "coefficient":
130                         // not used in Go (yet)
131                 case "created", "publish", "activate":
132                         // not used in Go (yet)
133                 }
134         }
135         return p, nil
136 }
137
138 func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
139         p := new(dsa.PrivateKey)
140         p.X = big.NewInt(0)
141         for k, v := range m {
142                 switch k {
143                 case "private_value(x)":
144                         v1, err := fromBase64([]byte(v))
145                         if err != nil {
146                                 return nil, err
147                         }
148                         p.X.SetBytes(v1)
149                 case "created", "publish", "activate":
150                         /* not used in Go (yet) */
151                 }
152         }
153         return p, nil
154 }
155
156 func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
157         p := new(ecdsa.PrivateKey)
158         p.D = big.NewInt(0)
159         // TODO: validate that the required flags are present
160         for k, v := range m {
161                 switch k {
162                 case "privatekey":
163                         v1, err := fromBase64([]byte(v))
164                         if err != nil {
165                                 return nil, err
166                         }
167                         p.D.SetBytes(v1)
168                 case "created", "publish", "activate":
169                         /* not used in Go (yet) */
170                 }
171         }
172         return p, nil
173 }
174
175 func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
176         var p ed25519.PrivateKey
177         // TODO: validate that the required flags are present
178         for k, v := range m {
179                 switch k {
180                 case "privatekey":
181                         p1, err := fromBase64([]byte(v))
182                         if err != nil {
183                                 return nil, err
184                         }
185                         if len(p1) != ed25519.SeedSize {
186                                 return nil, ErrPrivKey
187                         }
188                         p = ed25519.NewKeyFromSeed(p1)
189                 case "created", "publish", "activate":
190                         /* not used in Go (yet) */
191                 }
192         }
193         return p, nil
194 }
195
196 // parseKey reads a private key from r. It returns a map[string]string,
197 // with the key-value pairs, or an error when the file is not correct.
198 func parseKey(r io.Reader, file string) (map[string]string, error) {
199         m := make(map[string]string)
200         var k string
201
202         c := newKLexer(r)
203
204         for l, ok := c.Next(); ok; l, ok = c.Next() {
205                 // It should alternate
206                 switch l.value {
207                 case zKey:
208                         k = l.token
209                 case zValue:
210                         if k == "" {
211                                 return nil, &ParseError{file, "no private key seen", l}
212                         }
213
214                         m[strings.ToLower(k)] = l.token
215                         k = ""
216                 }
217         }
218
219         // Surface any read errors from r.
220         if err := c.Err(); err != nil {
221                 return nil, &ParseError{file: file, err: err.Error()}
222         }
223
224         return m, nil
225 }
226
227 type klexer struct {
228         br io.ByteReader
229
230         readErr error
231
232         line   int
233         column int
234
235         key bool
236
237         eol bool // end-of-line
238 }
239
240 func newKLexer(r io.Reader) *klexer {
241         br, ok := r.(io.ByteReader)
242         if !ok {
243                 br = bufio.NewReaderSize(r, 1024)
244         }
245
246         return &klexer{
247                 br: br,
248
249                 line: 1,
250
251                 key: true,
252         }
253 }
254
255 func (kl *klexer) Err() error {
256         if kl.readErr == io.EOF {
257                 return nil
258         }
259
260         return kl.readErr
261 }
262
263 // readByte returns the next byte from the input
264 func (kl *klexer) readByte() (byte, bool) {
265         if kl.readErr != nil {
266                 return 0, false
267         }
268
269         c, err := kl.br.ReadByte()
270         if err != nil {
271                 kl.readErr = err
272                 return 0, false
273         }
274
275         // delay the newline handling until the next token is delivered,
276         // fixes off-by-one errors when reporting a parse error.
277         if kl.eol {
278                 kl.line++
279                 kl.column = 0
280                 kl.eol = false
281         }
282
283         if c == '\n' {
284                 kl.eol = true
285         } else {
286                 kl.column++
287         }
288
289         return c, true
290 }
291
292 func (kl *klexer) Next() (lex, bool) {
293         var (
294                 l lex
295
296                 str bytes.Buffer
297
298                 commt bool
299         )
300
301         for x, ok := kl.readByte(); ok; x, ok = kl.readByte() {
302                 l.line, l.column = kl.line, kl.column
303
304                 switch x {
305                 case ':':
306                         if commt || !kl.key {
307                                 break
308                         }
309
310                         kl.key = false
311
312                         // Next token is a space, eat it
313                         kl.readByte()
314
315                         l.value = zKey
316                         l.token = str.String()
317                         return l, true
318                 case ';':
319                         commt = true
320                 case '\n':
321                         if commt {
322                                 // Reset a comment
323                                 commt = false
324                         }
325
326                         if kl.key && str.Len() == 0 {
327                                 // ignore empty lines
328                                 break
329                         }
330
331                         kl.key = true
332
333                         l.value = zValue
334                         l.token = str.String()
335                         return l, true
336                 default:
337                         if commt {
338                                 break
339                         }
340
341                         str.WriteByte(x)
342                 }
343         }
344
345         if kl.readErr != nil && kl.readErr != io.EOF {
346                 // Don't return any tokens after a read error occurs.
347                 return lex{value: zEOF}, false
348         }
349
350         if str.Len() > 0 {
351                 // Send remainder
352                 l.value = zValue
353                 l.token = str.String()
354                 return l, true
355         }
356
357         return lex{value: zEOF}, false
358 }