mirror of
https://github.com/miekg/dns.git
synced 2025-10-11 18:01:02 +02:00
incorp. in the main dns package
This commit is contained in:
parent
42ce4d3085
commit
4f8537dde2
4
TODO
4
TODO
@ -9,8 +9,7 @@ Short term:
|
|||||||
* Signature generation
|
* Signature generation
|
||||||
|
|
||||||
Issues:
|
Issues:
|
||||||
* Separation between dnssec and dns is arbitrary, why is tsig.go of package dns?
|
* escaped dots in names \.
|
||||||
* escaped dots in domain names: \.
|
|
||||||
* quoted quotes in txt records
|
* quoted quotes in txt records
|
||||||
* Better sized buffers
|
* Better sized buffers
|
||||||
* Check the network order, it works now, but this is on Intel
|
* Check the network order, it works now, but this is on Intel
|
||||||
@ -22,6 +21,7 @@ Issues:
|
|||||||
* query-time, server in string ouput of dns.Msg
|
* query-time, server in string ouput of dns.Msg
|
||||||
- DnsMsg when doing resolver querying, extend msg...?
|
- DnsMsg when doing resolver querying, extend msg...?
|
||||||
--
|
--
|
||||||
|
* remove the dns.Wire*() functions
|
||||||
|
|
||||||
Port over from LDNS:
|
Port over from LDNS:
|
||||||
* ldns-rrsig
|
* ldns-rrsig
|
||||||
|
@ -110,12 +110,6 @@ func (k *RR_DNSKEY) ToDS(h int) *RR_DS {
|
|||||||
return ds
|
return ds
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the key material and return the private key part. Only
|
|
||||||
// the key's algorithm field needs to be known
|
|
||||||
func (k *RR_DNSKEY) Generate() *RR_DS {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate an rrset with the signature and key. This is the
|
// Validate an rrset with the signature and key. This is the
|
||||||
// cryptographic test, the validity period most be check separately.
|
// cryptographic test, the validity period most be check separately.
|
||||||
func (s *RR_RRSIG) Verify(k *RR_DNSKEY, rrset RRset) bool {
|
func (s *RR_RRSIG) Verify(k *RR_DNSKEY, rrset RRset) bool {
|
||||||
|
@ -1 +0,0 @@
|
|||||||
miek.nl. 3600 IN DS 12273 8 2 beb0b9e415c223543e9cc1c76518839e6eb3bdec83103a2e90553e3a4db16f04 ; xozir-bevav-gahis-dymuh-gazan-sybys-lenyc-meban-vorir-fezuv-sibac-bovud-vegoh-hizyf-pyfor-cyrob-goxex
|
|
@ -1 +0,0 @@
|
|||||||
miek.nl. 3600 IN DNSKEY 256 3 8 AwEAAcELcuxHosJX3LjbR6EFzsqI3mKivwvO6Y5Kzt/OXYmLQUI8tnOrX9ilT/0qGraxoONayVX3A6bl1pG3h/xOxVEGcJGqbrZnhr2+4S9tW2GWQwevV+NhinE7v6MCCCheVCnAPh0KFb/u14ng3DQizP1spBU/NoAN31l678snBpZX ;{id = 12273 (zsk), size = 1024b}
|
|
@ -1,10 +0,0 @@
|
|||||||
Private-key-format: v1.2
|
|
||||||
Algorithm: 8 (RSASHA256)
|
|
||||||
Modulus: wQty7EeiwlfcuNtHoQXOyojeYqK/C87pjkrO385diYtBQjy2c6tf2KVP/SoatrGg41rJVfcDpuXWkbeH/E7FUQZwkaputmeGvb7hL21bYZZDB69X42GKcTu/owIIKF5UKcA+HQoVv+7XieDcNCLM/WykFT82gA3fWXrvyycGllc=
|
|
||||||
PublicExponent: AQAB
|
|
||||||
PrivateExponent: bp2R16Rgtf3Eo0Q7MiBy0wlEbL6WvDxvBjMFgabtYDAkT8EcRwFvJWPshsOGlSMJbt2JurGVLSBMKClDSacVVo4r86ND0ylj/1kfmHMEy49mu824Jbf9b1Aen4pR0I5KVAf0cHITY1xYag95C+Zdj91ymyBual+VLchBEIJ2NhE=
|
|
||||||
Prime1: 62QkvleT+6uDJRct5tqeDoRCxBIWWMFJ2+VgNsuo9+fCYhwjbFNHFV6BR20VrVWYH9WpuDKnxS0B41Jz6eDDDw==
|
|
||||||
Prime2: 0fIwIh53eBlCROIiZJfpFX1fPWsRD3/eX7W5VC5moFP/IiO+qLc8EFg4b2uCnmLJR07/vHowmv6yfpHjyDJYOQ==
|
|
||||||
Exponent1: 1ctLJCZfHgIVRybaZgbB7+VozrSu30YPU03uKVaozSEOiBWOhuDMezguqzUErz5CwQdK8yXvA0Nxp4pIBXBDOQ==
|
|
||||||
Exponent2: RQw0DGScwiD8jI8a5J6Zh/nNwvNdjw1s42lu5GLGWeCGPoInCHILDQ0Wsn5XXSP8MrmmniRJrBAsQDhXA9aa8Q==
|
|
||||||
Coefficient: Ntr5xV/6TtnlpNSg4WQNvaEdS7n7Lf7r+fS3/sHzqGkv8GT6gsRdQLQVu8Ml9t/GAPfUK4KsH7zmqr6N5dy9+g==
|
|
@ -1,12 +0,0 @@
|
|||||||
# Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style
|
|
||||||
# license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
include $(GOROOT)/src/Make.inc
|
|
||||||
|
|
||||||
TARG=dns/dnssec
|
|
||||||
GOFILES=\
|
|
||||||
dnssec.go\
|
|
||||||
|
|
||||||
DEPS=..
|
|
||||||
include $(GOROOT)/src/Make.pkg
|
|
272
dnssec/dnssec.go
272
dnssec/dnssec.go
@ -1,272 +0,0 @@
|
|||||||
// Package dnssec implements all client side DNSSEC function, like
|
|
||||||
// validation, keytag and DS calculation.
|
|
||||||
package dnssec
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/sha512"
|
|
||||||
"crypto/rsa"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/base64"
|
|
||||||
"hash"
|
|
||||||
"time"
|
|
||||||
"io"
|
|
||||||
"big"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"os"
|
|
||||||
"dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DNSSEC encryption algorithm codes.
|
|
||||||
const (
|
|
||||||
// DNSSEC algorithms
|
|
||||||
AlgRSAMD5 = 1
|
|
||||||
AlgDH = 2
|
|
||||||
AlgDSA = 3
|
|
||||||
AlgECC = 4
|
|
||||||
AlgRSASHA1 = 5
|
|
||||||
AlgRSASHA256 = 8
|
|
||||||
AlgRSASHA512 = 10
|
|
||||||
AlgECCGOST = 12
|
|
||||||
)
|
|
||||||
|
|
||||||
// DNSSEC hashing codes.
|
|
||||||
const (
|
|
||||||
HashSHA1 = iota
|
|
||||||
HashSHA256
|
|
||||||
HashGOST94
|
|
||||||
)
|
|
||||||
|
|
||||||
// Convert an DNSKEY record to a DS record.
|
|
||||||
func ToDS(k *dns.RR_DNSKEY, hash int) *dns.RR_DS {
|
|
||||||
ds := new(dns.RR_DS)
|
|
||||||
ds.Hdr.Name = k.Hdr.Name
|
|
||||||
ds.Hdr.Class = k.Hdr.Class
|
|
||||||
ds.Hdr.Ttl = k.Hdr.Ttl
|
|
||||||
ds.Algorithm = k.Algorithm
|
|
||||||
ds.DigestType = uint8(hash)
|
|
||||||
ds.KeyTag = KeyTag(k)
|
|
||||||
|
|
||||||
wire, ok := dns.WireRdata(k)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
owner, ok1 := dns.WireDomainName(k.Hdr.Name)
|
|
||||||
if !ok1 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* from RFC4034
|
|
||||||
* digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
|
|
||||||
* "|" denotes concatenation
|
|
||||||
* DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
|
|
||||||
*/
|
|
||||||
// digest buffer
|
|
||||||
digest := append(owner, wire...) // another copy TODO(mg)
|
|
||||||
|
|
||||||
switch hash {
|
|
||||||
case HashSHA1:
|
|
||||||
s := sha1.New()
|
|
||||||
io.WriteString(s, string(digest))
|
|
||||||
ds.Digest = hex.EncodeToString(s.Sum())
|
|
||||||
case HashSHA256:
|
|
||||||
s := sha256.New()
|
|
||||||
io.WriteString(s, string(digest))
|
|
||||||
ds.Digest = hex.EncodeToString(s.Sum())
|
|
||||||
case HashGOST94:
|
|
||||||
|
|
||||||
default:
|
|
||||||
// wrong hash value
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return ds
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the keytag of the DNSKEY.
|
|
||||||
func KeyTag(k *dns.RR_DNSKEY) uint16 {
|
|
||||||
var keytag int
|
|
||||||
switch k.Algorithm {
|
|
||||||
case AlgRSAMD5:
|
|
||||||
println("Keytag RSAMD5. Todo")
|
|
||||||
keytag = 0
|
|
||||||
default:
|
|
||||||
// Might encode header length too, so that
|
|
||||||
// we dont need to pack/unpack all the time
|
|
||||||
// Or a shadow structure, with the wiredata and header
|
|
||||||
wire, ok := dns.WireRdata(k)
|
|
||||||
if !ok {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
for i, v := range wire {
|
|
||||||
if i&1 != 0 {
|
|
||||||
keytag += int(v) // must be larger than uint32
|
|
||||||
} else {
|
|
||||||
keytag += int(v) << 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keytag += (keytag >> 16) & 0xFFFF
|
|
||||||
keytag &= 0xFFFF
|
|
||||||
}
|
|
||||||
return uint16(keytag)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate an rrset with the signature and key. This is the
|
|
||||||
// cryptographic test, the validity period most be check separately.
|
|
||||||
func Verify(s *dns.RR_RRSIG, k *dns.RR_DNSKEY, rrset dns.RRset) bool {
|
|
||||||
// Frist the easy checks
|
|
||||||
if s.KeyTag != KeyTag(k) {
|
|
||||||
println(s.KeyTag)
|
|
||||||
println(KeyTag(k))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.Hdr.Class != k.Hdr.Class {
|
|
||||||
println("Class")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.Algorithm != k.Algorithm {
|
|
||||||
println("Class")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if s.SignerName != k.Hdr.Name {
|
|
||||||
println(s.SignerName)
|
|
||||||
println(k.Hdr.Name)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, r := range rrset {
|
|
||||||
if r.Header().Class != s.Hdr.Class {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if r.Header().Rrtype != s.TypeCovered {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Number of labels. TODO(mg) add helper functions
|
|
||||||
}
|
|
||||||
sort.Sort(rrset)
|
|
||||||
|
|
||||||
// RFC 4035 5.3.2. Reconstructing the Signed Data
|
|
||||||
// Copy the sig, except the rrsig data
|
|
||||||
s1 := &dns.RR_RRSIG{s.Hdr, s.TypeCovered, s.Algorithm, s.Labels, s.OrigTtl, s.Expiration, s.Inception, s.KeyTag, s.SignerName, ""}
|
|
||||||
signeddata, ok := dns.WireRdata(s1)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range rrset {
|
|
||||||
h := r.Header()
|
|
||||||
// RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase
|
|
||||||
name := h.Name
|
|
||||||
h.Name = strings.ToLower(h.Name)
|
|
||||||
// 6.2. Canonical RR Form. (3) - domain rdata to lowercaser
|
|
||||||
switch h.Rrtype {
|
|
||||||
case dns.TypeNS, dns.TypeCNAME, dns.TypeSOA, dns.TypeMB, dns.TypeMG, dns.TypeMR, dns.TypePTR:
|
|
||||||
case dns.TypeHINFO, dns.TypeMINFO, dns.TypeMX /* dns.TypeRP, dns.TypeAFSDB, dns.TypeRT */ :
|
|
||||||
case dns.TypeSIG /* dns.TypePX, dns.TypeNXT /* dns.TypeNAPTR, dns.TypeKX */ :
|
|
||||||
case dns.TypeSRV, /* dns.TypeDNAME, dns.TypeA6 */ dns.TypeRRSIG, dns.TypeNSEC:
|
|
||||||
// lower case the domain rdata //
|
|
||||||
|
|
||||||
}
|
|
||||||
// 6.2. Canonical RR Form. (4) - wildcards, don't understand
|
|
||||||
// 6.2. Canonical RR Form. (5) - origTTL
|
|
||||||
ttl := h.Ttl
|
|
||||||
h.Ttl = s.OrigTtl
|
|
||||||
wire, ok1 := dns.WireRR(r)
|
|
||||||
h.Ttl = ttl // restore the order in the universe
|
|
||||||
h.Name = name
|
|
||||||
if !ok1 {
|
|
||||||
println("Failure to pack")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
signeddata = append(signeddata, wire...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buffer holding the key data
|
|
||||||
keybuf := make([]byte, 1024)
|
|
||||||
keybuflen := base64.StdEncoding.DecodedLen(len(k.PubKey))
|
|
||||||
keybuflen, _ = base64.StdEncoding.Decode(keybuf[0:keybuflen], []byte(k.PubKey))
|
|
||||||
keybuf = keybuf[:keybuflen]
|
|
||||||
|
|
||||||
// Buffer holding the signature
|
|
||||||
sigbuf := make([]byte, 1024)
|
|
||||||
sigbuflen := base64.StdEncoding.DecodedLen(len(s.Signature))
|
|
||||||
sigbuflen, _ = base64.StdEncoding.Decode(sigbuf[0:sigbuflen], []byte(s.Signature))
|
|
||||||
sigbuf = sigbuf[:sigbuflen]
|
|
||||||
|
|
||||||
var err os.Error
|
|
||||||
switch s.Algorithm {
|
|
||||||
case AlgRSASHA1, AlgRSASHA256, AlgRSASHA512, AlgRSAMD5:
|
|
||||||
pubkey := rsaPubKey(keybuf)
|
|
||||||
// Setup the hash as defined for this alg.
|
|
||||||
var h hash.Hash
|
|
||||||
var ch rsa.PKCS1v15Hash
|
|
||||||
switch s.Algorithm {
|
|
||||||
case AlgRSAMD5:
|
|
||||||
h = md5.New()
|
|
||||||
ch = rsa.HashMD5
|
|
||||||
case AlgRSASHA1:
|
|
||||||
h = sha1.New()
|
|
||||||
ch = rsa.HashSHA1
|
|
||||||
case AlgRSASHA256:
|
|
||||||
h = sha256.New()
|
|
||||||
ch = rsa.HashSHA256
|
|
||||||
case AlgRSASHA512:
|
|
||||||
h = sha512.New()
|
|
||||||
ch = rsa.HashSHA512
|
|
||||||
}
|
|
||||||
io.WriteString(h, string(signeddata))
|
|
||||||
sighash := h.Sum()
|
|
||||||
err = rsa.VerifyPKCS1v15(pubkey, ch, sighash, sigbuf)
|
|
||||||
case AlgDH:
|
|
||||||
case AlgDSA:
|
|
||||||
case AlgECC:
|
|
||||||
case AlgECCGOST:
|
|
||||||
}
|
|
||||||
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using RFC1982 calculate if a signature period is valid
|
|
||||||
func PeriodOK(s *dns.RR_RRSIG) bool {
|
|
||||||
utc := time.UTC().Seconds()
|
|
||||||
modi := (int64(s.Inception) - utc) / dns.Year68
|
|
||||||
mode := (int64(s.Expiration) - utc) / dns.Year68
|
|
||||||
ti := int64(s.Inception) + (modi * dns.Year68)
|
|
||||||
te := int64(s.Expiration) + (mode * dns.Year68)
|
|
||||||
return ti <= utc && utc <= te
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extra the RSA public key from the buffer
|
|
||||||
func rsaPubKey(keybuf []byte) *rsa.PublicKey {
|
|
||||||
// RFC 2537/3110, section 2. RSA Public KEY Resource Records
|
|
||||||
// Length is in the 0th byte, unless its zero, then it
|
|
||||||
// it in bytes 1 and 2 and its a 16 bit number
|
|
||||||
explen := uint16(keybuf[0])
|
|
||||||
keyoff := 1
|
|
||||||
if explen == 0 {
|
|
||||||
explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
|
|
||||||
keyoff = 3
|
|
||||||
}
|
|
||||||
pubkey := new(rsa.PublicKey)
|
|
||||||
pubkey.N = big.NewInt(0)
|
|
||||||
shift := (explen - 1) * 8
|
|
||||||
for i := int(explen - 1); i >= 0; i-- {
|
|
||||||
pubkey.E += int(keybuf[keyoff+i]) << shift
|
|
||||||
shift -= 8
|
|
||||||
}
|
|
||||||
pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
|
|
||||||
return pubkey
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map for algorithm names.
|
|
||||||
var alg_str = map[uint8]string{
|
|
||||||
AlgRSAMD5: "RSAMD5",
|
|
||||||
AlgDH: "DH",
|
|
||||||
AlgDSA: "DSA",
|
|
||||||
AlgRSASHA1: "RSASHA1",
|
|
||||||
AlgRSASHA256: "RSASHA256",
|
|
||||||
AlgRSASHA512: "RSASHA512",
|
|
||||||
AlgECCGOST: "ECC-GOST",
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user