From 45362590377a7a6b8194c32da1f0772cbeac39ec Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Tue, 17 Apr 2012 11:39:58 +0200 Subject: [PATCH] 1/2 support for DSA --- TODO.markdown | 2 +- dnssec.go | 43 ++++++++++++++++++++++++++++++++++++++++++- kscan.go | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/TODO.markdown b/TODO.markdown index f6a12b63..f6502862 100644 --- a/TODO.markdown +++ b/TODO.markdown @@ -6,7 +6,7 @@ need to be fixed. * Speed, we can always go faster. A simple reflect server now hits 35/45K qps * go test; only works correct on my machine * Add handy zone data structure (r/b tree)? Or not... -* dnssec: DSA (also the keytag) +* privatekey.Precompute() when signing? ## Examples to add diff --git a/dnssec.go b/dnssec.go index ec946d00..3d9d7898 100644 --- a/dnssec.go +++ b/dnssec.go @@ -16,6 +16,7 @@ package dns import ( "bytes" "crypto" + "crypto/dsa" "crypto/ecdsa" "crypto/elliptic" "crypto/md5" @@ -432,8 +433,18 @@ func (s *RR_RRSIG) sigBuf() []byte { // setPublicKeyInPrivate sets the public key in the private key. func (k *RR_DNSKEY) setPublicKeyInPrivate(p PrivateKey) bool { switch t := p.(type) { + case *dsa.PrivateKey: + x := k.publicKeyDSA() + if x == nil { + return false + } + t.PublicKey = *x case *rsa.PrivateKey: - // Something - but the + x := k.publicKeyRSA() + if x == nil { + return false + } + t.PublicKey = *x case *ecdsa.PrivateKey: x := k.publicKeyCurve() if x == nil { @@ -510,6 +521,28 @@ func (k *RR_DNSKEY) publicKeyCurve() *ecdsa.PublicKey { return pubkey } +func (k *RR_DNSKEY) publicKeyDSA() *dsa.PublicKey { + keybuf, err := packBase64([]byte(k.PublicKey)) + if err != nil { + return nil + } + if len(keybuf) < 22 { // TODO: check + return nil + } + t := int(keybuf[0]) + size := 64 + t*8 + pubkey := new(dsa.PublicKey) + pubkey.Parameters.Q = big.NewInt(0) + pubkey.Parameters.Q.SetBytes(keybuf[1:21]) // +/- 1 ? + pubkey.Parameters.P = big.NewInt(0) + pubkey.Parameters.P.SetBytes(keybuf[22:22+size]) + pubkey.Parameters.G = big.NewInt(0) + pubkey.Parameters.G.SetBytes(keybuf[22+size+1:22+size*2]) + pubkey.Y = big.NewInt(0) + pubkey.Y.SetBytes(keybuf[22+size*2+1:22+size*3]) + return pubkey +} + // Set the public key (the value E and N) func (k *RR_DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool { if _E == 0 || _N == nil { @@ -532,6 +565,14 @@ func (k *RR_DNSKEY) setPublicKeyCurve(_X, _Y *big.Int) bool { return true } +// Set the public key for DSA +func (k RR_DNSKEY) setPublicKeyDSA(_P, _Q, _G, _Y *big.Int) bool { + if _P == nil || _Q == nil || _G == nil || _Y == nil { + return false + } + return true +} + // Set the public key (the values E and N) for RSA // RFC 3110: Section 2. RSA Public KEY Resource Records func exponentToBuf(_E int) []byte { diff --git a/kscan.go b/kscan.go index 0fea1625..c41e16b4 100644 --- a/kscan.go +++ b/kscan.go @@ -3,6 +3,7 @@ package dns import ( "crypto/ecdsa" "crypto/rsa" + "crypto/dsa" "io" "math/big" "strings" @@ -30,15 +31,24 @@ func (k *RR_DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) } // TODO(mg): check if the pubkey matches the private key switch m["algorithm"] { + case "3 (DSA)": + p, e := readPrivateKeyDSA(m) + if e != nil { + return nil, e + } + if !k.setPublicKeyInPrivate(p) { + return nil, ErrPrivKey + } + return p, e case "1 (RSAMD5)": fallthrough case "5 (RSASHA1)": fallthrough + case "7 (RSASHA1NSEC3SHA1)": + fallthrough case "8 (RSASHA256)": fallthrough case "10 (RSASHA512)": - fallthrough - case "7 (RSASHA1NSEC3SHA1)": p, e := readPrivateKeyRSA(m) if e != nil { return nil, e @@ -107,6 +117,24 @@ func readPrivateKeyRSA(m map[string]string) (PrivateKey, error) { return p, nil } +func readPrivateKeyDSA(m map[string]string) (PrivateKey, error) { + p := new(dsa.PrivateKey) + p.X = big.NewInt(0) + for k, v := range m { + switch k { + case "private_value(x):": + v1, err := packBase64([]byte(v)) + if err != nil { + return nil, err + } + p.X.SetBytes(v1) + case "created:", "publish:", "activate:": + /* not used in Go (yet) */ + } + } + return p, nil +} + func readPrivateKeyECDSA(m map[string]string) (PrivateKey, error) { p := new(ecdsa.PrivateKey) p.D = big.NewInt(0)