23 "golang.org/x/crypto/ed25519"
26 // DNSSEC encryption algorithm codes.
32 _ // Skip 4, RFC 6725, section 2.1
37 _ // Skip 9, RFC 6725, section 2.1
39 _ // Skip 11, RFC 6725, section 2.1
46 PRIVATEDNS uint8 = 253 // Private (experimental keys)
47 PRIVATEOID uint8 = 254
50 // AlgorithmToString is a map of algorithm IDs to algorithm names.
51 var AlgorithmToString = map[uint8]string{
56 DSANSEC3SHA1: "DSA-NSEC3-SHA1",
57 RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
58 RSASHA256: "RSASHA256",
59 RSASHA512: "RSASHA512",
61 ECDSAP256SHA256: "ECDSAP256SHA256",
62 ECDSAP384SHA384: "ECDSAP384SHA384",
66 PRIVATEDNS: "PRIVATEDNS",
67 PRIVATEOID: "PRIVATEOID",
70 // AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
71 var AlgorithmToHash = map[uint8]crypto.Hash{
72 RSAMD5: crypto.MD5, // Deprecated in RFC 6725
75 RSASHA1NSEC3SHA1: crypto.SHA1,
76 RSASHA256: crypto.SHA256,
77 ECDSAP256SHA256: crypto.SHA256,
78 ECDSAP384SHA384: crypto.SHA384,
79 RSASHA512: crypto.SHA512,
80 ED25519: crypto.Hash(0),
83 // DNSSEC hashing algorithm codes.
89 SHA384 // Experimental
90 SHA512 // Experimental
93 // HashToString is a map of hash IDs to names.
94 var HashToString = map[uint8]string{
102 // DNSKEY flag values.
109 // The RRSIG needs to be converted to wireformat with some of the rdata (the signature) missing.
110 type rrsigWireFmt struct {
118 SignerName string `dns:"domain-name"`
122 // Used for converting DNSKEY's rdata to wirefmt.
123 type dnskeyWireFmt struct {
127 PublicKey string `dns:"base64"`
128 /* Nothing is left out */
131 func divRoundUp(a, b int) int {
132 return (a + b - 1) / b
135 // KeyTag calculates the keytag (or key-id) of the DNSKEY.
136 func (k *DNSKEY) KeyTag() uint16 {
143 // Look at the bottom two bytes of the modules, which the last
144 // item in the pubkey. We could do this faster by looking directly
145 // at the base64 values. But I'm lazy.
146 modulus, _ := fromBase64([]byte(k.PublicKey))
147 if len(modulus) > 1 {
148 x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
152 keywire := new(dnskeyWireFmt)
153 keywire.Flags = k.Flags
154 keywire.Protocol = k.Protocol
155 keywire.Algorithm = k.Algorithm
156 keywire.PublicKey = k.PublicKey
157 wire := make([]byte, DefaultMsgSize)
158 n, err := packKeyWire(keywire, wire)
163 for i, v := range wire {
165 keytag += int(v) // must be larger than uint32
167 keytag += int(v) << 8
170 keytag += keytag >> 16 & 0xFFFF
173 return uint16(keytag)
176 // ToDS converts a DNSKEY record to a DS record.
177 func (k *DNSKEY) ToDS(h uint8) *DS {
182 ds.Hdr.Name = k.Hdr.Name
183 ds.Hdr.Class = k.Hdr.Class
184 ds.Hdr.Rrtype = TypeDS
185 ds.Hdr.Ttl = k.Hdr.Ttl
186 ds.Algorithm = k.Algorithm
188 ds.KeyTag = k.KeyTag()
190 keywire := new(dnskeyWireFmt)
191 keywire.Flags = k.Flags
192 keywire.Protocol = k.Protocol
193 keywire.Algorithm = k.Algorithm
194 keywire.PublicKey = k.PublicKey
195 wire := make([]byte, DefaultMsgSize)
196 n, err := packKeyWire(keywire, wire)
202 owner := make([]byte, 255)
203 off, err1 := PackDomainName(strings.ToLower(k.Hdr.Name), owner, 0, nil, false)
209 // digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
210 // "|" denotes concatenation
211 // DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
230 ds.Digest = hex.EncodeToString(s.Sum(nil))
234 // ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
235 func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
236 c := &CDNSKEY{DNSKEY: *k}
238 c.Hdr.Rrtype = TypeCDNSKEY
242 // ToCDS converts a DS record to a CDS record.
243 func (d *DS) ToCDS() *CDS {
246 c.Hdr.Rrtype = TypeCDS
250 // Sign signs an RRSet. The signature needs to be filled in with the values:
251 // Inception, Expiration, KeyTag, SignerName and Algorithm. The rest is copied
252 // from the RRset. Sign returns a non-nill error when the signing went OK.
253 // There is no check if RRSet is a proper (RFC 2181) RRSet. If OrigTTL is non
254 // zero, it is used as-is, otherwise the TTL of the RRset is used as the
256 func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
260 // s.Inception and s.Expiration may be 0 (rollover etc.), the rest must be set
261 if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
265 h0 := rrset[0].Header()
266 rr.Hdr.Rrtype = TypeRRSIG
267 rr.Hdr.Name = h0.Name
268 rr.Hdr.Class = h0.Class
269 if rr.OrigTtl == 0 { // If set don't override
272 rr.TypeCovered = h0.Rrtype
273 rr.Labels = uint8(CountLabel(h0.Name))
275 if strings.HasPrefix(h0.Name, "*") {
276 rr.Labels-- // wildcard, remove from label count
279 sigwire := new(rrsigWireFmt)
280 sigwire.TypeCovered = rr.TypeCovered
281 sigwire.Algorithm = rr.Algorithm
282 sigwire.Labels = rr.Labels
283 sigwire.OrigTtl = rr.OrigTtl
284 sigwire.Expiration = rr.Expiration
285 sigwire.Inception = rr.Inception
286 sigwire.KeyTag = rr.KeyTag
287 // For signing, lowercase this name
288 sigwire.SignerName = strings.ToLower(rr.SignerName)
290 // Create the desired binary blob
291 signdata := make([]byte, DefaultMsgSize)
292 n, err := packSigWire(sigwire, signdata)
296 signdata = signdata[:n]
297 wire, err := rawSignatureData(rrset, rr)
302 hash, ok := AlgorithmToHash[rr.Algorithm]
307 switch rr.Algorithm {
309 // ed25519 signs the raw message and performs hashing internally.
310 // All other supported signature schemes operate over the pre-hashed
311 // message, and thus ed25519 must be handled separately here.
313 // The raw message is passed directly into sign and crypto.Hash(0) is
314 // used to signal to the crypto.Signer that the data has not been hashed.
315 signature, err := sign(k, append(signdata, wire...), crypto.Hash(0), rr.Algorithm)
320 rr.Signature = toBase64(signature)
326 signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
331 rr.Signature = toBase64(signature)
337 func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
338 signature, err := k.Sign(rand.Reader, hashed, hash)
344 case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
345 return signature, nil
347 case ECDSAP256SHA256, ECDSAP384SHA384:
348 ecdsaSignature := &struct {
351 if _, err := asn1.Unmarshal(signature, ecdsaSignature); err != nil {
357 case ECDSAP256SHA256:
359 case ECDSAP384SHA384:
363 signature := intToBytes(ecdsaSignature.R, intlen)
364 signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
365 return signature, nil
367 // There is no defined interface for what a DSA backed crypto.Signer returns
368 case DSA, DSANSEC3SHA1:
369 // t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
370 // signature := []byte{byte(t)}
371 // signature = append(signature, intToBytes(r1, 20)...)
372 // signature = append(signature, intToBytes(s1, 20)...)
373 // rr.Signature = signature
376 return signature, nil
382 // Verify validates an RRSet with the signature and key. This is only the
383 // cryptographic test, the signature validity period must be checked separately.
384 // This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
385 func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
386 // First the easy checks
390 if rr.KeyTag != k.KeyTag() {
393 if rr.Hdr.Class != k.Hdr.Class {
396 if rr.Algorithm != k.Algorithm {
399 if !strings.EqualFold(rr.SignerName, k.Hdr.Name) {
406 // IsRRset checked that we have at least one RR and that the RRs in
407 // the set have consistent type, class, and name. Also check that type and
408 // class matches the RRSIG record.
409 if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered {
413 // RFC 4035 5.3.2. Reconstructing the Signed Data
414 // Copy the sig, except the rrsig data
415 sigwire := new(rrsigWireFmt)
416 sigwire.TypeCovered = rr.TypeCovered
417 sigwire.Algorithm = rr.Algorithm
418 sigwire.Labels = rr.Labels
419 sigwire.OrigTtl = rr.OrigTtl
420 sigwire.Expiration = rr.Expiration
421 sigwire.Inception = rr.Inception
422 sigwire.KeyTag = rr.KeyTag
423 sigwire.SignerName = strings.ToLower(rr.SignerName)
424 // Create the desired binary blob
425 signeddata := make([]byte, DefaultMsgSize)
426 n, err := packSigWire(sigwire, signeddata)
430 signeddata = signeddata[:n]
431 wire, err := rawSignatureData(rrset, rr)
436 sigbuf := rr.sigBuf() // Get the binary signature data
437 if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
439 // remove the domain name and assume its ours?
442 hash, ok := AlgorithmToHash[rr.Algorithm]
447 switch rr.Algorithm {
448 case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5:
449 // TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
450 pubkey := k.publicKeyRSA() // Get the key
458 return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
460 case ECDSAP256SHA256, ECDSAP384SHA384:
461 pubkey := k.publicKeyECDSA()
466 // Split sigbuf into the r and s coordinates
467 r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2])
468 s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:])
473 if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
479 pubkey := k.publicKeyED25519()
484 if ed25519.Verify(pubkey, append(signeddata, wire...), sigbuf) {
494 // ValidityPeriod uses RFC1982 serial arithmetic to calculate
495 // if a signature period is valid. If t is the zero time, the
496 // current time is taken other t is. Returns true if the signature
497 // is valid at the given time, otherwise returns false.
498 func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
501 utc = time.Now().UTC().Unix()
505 modi := (int64(rr.Inception) - utc) / year68
506 mode := (int64(rr.Expiration) - utc) / year68
507 ti := int64(rr.Inception) + modi*year68
508 te := int64(rr.Expiration) + mode*year68
509 return ti <= utc && utc <= te
512 // Return the signatures base64 encodedig sigdata as a byte slice.
513 func (rr *RRSIG) sigBuf() []byte {
514 sigbuf, err := fromBase64([]byte(rr.Signature))
521 // publicKeyRSA returns the RSA public key from a DNSKEY record.
522 func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
523 keybuf, err := fromBase64([]byte(k.PublicKey))
528 if len(keybuf) < 1+1+64 {
529 // Exponent must be at least 1 byte and modulus at least 64
533 // RFC 2537/3110, section 2. RSA Public KEY Resource Records
534 // Length is in the 0th byte, unless its zero, then it
535 // it in bytes 1 and 2 and its a 16 bit number
536 explen := uint16(keybuf[0])
539 explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
543 if explen > 4 || explen == 0 || keybuf[keyoff] == 0 {
544 // Exponent larger than supported by the crypto package,
545 // empty, or contains prohibited leading zero.
549 modoff := keyoff + int(explen)
550 modlen := len(keybuf) - modoff
551 if modlen < 64 || modlen > 512 || keybuf[modoff] == 0 {
552 // Modulus is too small, large, or contains prohibited leading zero.
556 pubkey := new(rsa.PublicKey)
559 for i := 0; i < int(explen); i++ {
561 expo |= uint64(keybuf[keyoff+i])
564 // Larger exponent than supported by the crypto package.
569 pubkey.N = big.NewInt(0)
570 pubkey.N.SetBytes(keybuf[modoff:])
575 // publicKeyECDSA returns the Curve public key from the DNSKEY record.
576 func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
577 keybuf, err := fromBase64([]byte(k.PublicKey))
581 pubkey := new(ecdsa.PublicKey)
583 case ECDSAP256SHA256:
584 pubkey.Curve = elliptic.P256()
585 if len(keybuf) != 64 {
586 // wrongly encoded key
589 case ECDSAP384SHA384:
590 pubkey.Curve = elliptic.P384()
591 if len(keybuf) != 96 {
592 // Wrongly encoded key
596 pubkey.X = big.NewInt(0)
597 pubkey.X.SetBytes(keybuf[:len(keybuf)/2])
598 pubkey.Y = big.NewInt(0)
599 pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
603 func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
604 keybuf, err := fromBase64([]byte(k.PublicKey))
608 if len(keybuf) < 22 {
611 t, keybuf := int(keybuf[0]), keybuf[1:]
613 q, keybuf := keybuf[:20], keybuf[20:]
614 if len(keybuf) != 3*size {
617 p, keybuf := keybuf[:size], keybuf[size:]
618 g, y := keybuf[:size], keybuf[size:]
619 pubkey := new(dsa.PublicKey)
620 pubkey.Parameters.Q = big.NewInt(0).SetBytes(q)
621 pubkey.Parameters.P = big.NewInt(0).SetBytes(p)
622 pubkey.Parameters.G = big.NewInt(0).SetBytes(g)
623 pubkey.Y = big.NewInt(0).SetBytes(y)
627 func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey {
628 keybuf, err := fromBase64([]byte(k.PublicKey))
632 if len(keybuf) != ed25519.PublicKeySize {
638 type wireSlice [][]byte
640 func (p wireSlice) Len() int { return len(p) }
641 func (p wireSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
642 func (p wireSlice) Less(i, j int) bool {
643 _, ioff, _ := UnpackDomainName(p[i], 0)
644 _, joff, _ := UnpackDomainName(p[j], 0)
645 return bytes.Compare(p[i][ioff+10:], p[j][joff+10:]) < 0
648 // Return the raw signature data.
649 func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
650 wires := make(wireSlice, len(rrset))
651 for i, r := range rrset {
655 labels := SplitDomainName(h.Name)
656 // 6.2. Canonical RR Form. (4) - wildcards
657 if len(labels) > int(s.Labels) {
659 h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
661 // RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase
662 h.Name = strings.ToLower(h.Name)
663 // 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
664 // NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
665 // HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
668 // RFC 6840 - Clarifications and Implementation Notes for DNS Security (DNSSEC):
669 // Section 6.2 of [RFC4034] also erroneously lists HINFO as a record
670 // that needs conversion to lowercase, and twice at that. Since HINFO
671 // records contain no domain names, they are not subject to case
673 switch x := r1.(type) {
675 x.Ns = strings.ToLower(x.Ns)
677 x.Md = strings.ToLower(x.Md)
679 x.Mf = strings.ToLower(x.Mf)
681 x.Target = strings.ToLower(x.Target)
683 x.Ns = strings.ToLower(x.Ns)
684 x.Mbox = strings.ToLower(x.Mbox)
686 x.Mb = strings.ToLower(x.Mb)
688 x.Mg = strings.ToLower(x.Mg)
690 x.Mr = strings.ToLower(x.Mr)
692 x.Ptr = strings.ToLower(x.Ptr)
694 x.Rmail = strings.ToLower(x.Rmail)
695 x.Email = strings.ToLower(x.Email)
697 x.Mx = strings.ToLower(x.Mx)
699 x.Mbox = strings.ToLower(x.Mbox)
700 x.Txt = strings.ToLower(x.Txt)
702 x.Hostname = strings.ToLower(x.Hostname)
704 x.Host = strings.ToLower(x.Host)
706 x.SignerName = strings.ToLower(x.SignerName)
708 x.Map822 = strings.ToLower(x.Map822)
709 x.Mapx400 = strings.ToLower(x.Mapx400)
711 x.Replacement = strings.ToLower(x.Replacement)
713 x.Exchanger = strings.ToLower(x.Exchanger)
715 x.Target = strings.ToLower(x.Target)
717 x.Target = strings.ToLower(x.Target)
719 // 6.2. Canonical RR Form. (5) - origTTL
720 wire := make([]byte, Len(r1)+1) // +1 to be safe(r)
721 off, err1 := PackRR(r1, wire, 0, nil, false)
729 for i, wire := range wires {
730 if i > 0 && bytes.Equal(wire, wires[i-1]) {
733 buf = append(buf, wire...)
738 func packSigWire(sw *rrsigWireFmt, msg []byte) (int, error) {
739 // copied from zmsg.go RRSIG packing
740 off, err := packUint16(sw.TypeCovered, msg, 0)
744 off, err = packUint8(sw.Algorithm, msg, off)
748 off, err = packUint8(sw.Labels, msg, off)
752 off, err = packUint32(sw.OrigTtl, msg, off)
756 off, err = packUint32(sw.Expiration, msg, off)
760 off, err = packUint32(sw.Inception, msg, off)
764 off, err = packUint16(sw.KeyTag, msg, off)
768 off, err = PackDomainName(sw.SignerName, msg, off, nil, false)
775 func packKeyWire(dw *dnskeyWireFmt, msg []byte) (int, error) {
776 // copied from zmsg.go DNSKEY packing
777 off, err := packUint16(dw.Flags, msg, 0)
781 off, err = packUint8(dw.Protocol, msg, off)
785 off, err = packUint8(dw.Algorithm, msg, off)
789 off, err = packStringBase64(dw.PublicKey, msg, off)