mirror of
https://github.com/miekg/dns.git
synced 2025-08-11 20:16:58 +02:00
This will allow RRSIG.Sign to use generic crypto.Signer implementations. This is a interface breaking change, even if the required changes are most likely just type asserions from crypto.PrivateKey to the underlying type or crypto.Signer.
723 lines
23 KiB
Go
723 lines
23 KiB
Go
package dns
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/ecdsa"
|
|
"crypto/rsa"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func getKey() *DNSKEY {
|
|
key := new(DNSKEY)
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 14400
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = RSASHA256
|
|
key.PublicKey = "AwEAAcNEU67LJI5GEgF9QLNqLO1SMq1EdoQ6E9f85ha0k0ewQGCblyW2836GiVsm6k8Kr5ECIoMJ6fZWf3CQSQ9ycWfTyOHfmI3eQ/1Covhb2y4bAmL/07PhrL7ozWBW3wBfM335Ft9xjtXHPy7ztCbV9qZ4TVDTW/Iyg0PiwgoXVesz"
|
|
return key
|
|
}
|
|
|
|
func getSoa() *SOA {
|
|
soa := new(SOA)
|
|
soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0}
|
|
soa.Ns = "open.nlnetlabs.nl."
|
|
soa.Mbox = "miekg.atoom.net."
|
|
soa.Serial = 1293945905
|
|
soa.Refresh = 14400
|
|
soa.Retry = 3600
|
|
soa.Expire = 604800
|
|
soa.Minttl = 86400
|
|
return soa
|
|
}
|
|
|
|
func TestGenerateEC(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping test in short mode.")
|
|
}
|
|
key := new(DNSKEY)
|
|
key.Hdr.Rrtype = TypeDNSKEY
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 14400
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = ECDSAP256SHA256
|
|
privkey, _ := key.Generate(256)
|
|
t.Log(key.String())
|
|
t.Log(key.PrivateKeyString(privkey))
|
|
}
|
|
|
|
func TestGenerateDSA(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping test in short mode.")
|
|
}
|
|
key := new(DNSKEY)
|
|
key.Hdr.Rrtype = TypeDNSKEY
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 14400
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = DSA
|
|
privkey, _ := key.Generate(1024)
|
|
t.Log(key.String())
|
|
t.Log(key.PrivateKeyString(privkey))
|
|
}
|
|
|
|
func TestGenerateRSA(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping test in short mode.")
|
|
}
|
|
key := new(DNSKEY)
|
|
key.Hdr.Rrtype = TypeDNSKEY
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 14400
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = RSASHA256
|
|
privkey, _ := key.Generate(1024)
|
|
t.Log(key.String())
|
|
t.Log(key.PrivateKeyString(privkey))
|
|
}
|
|
|
|
func TestSecure(t *testing.T) {
|
|
soa := getSoa()
|
|
|
|
sig := new(RRSIG)
|
|
sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
|
|
sig.TypeCovered = TypeSOA
|
|
sig.Algorithm = RSASHA256
|
|
sig.Labels = 2
|
|
sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
|
|
sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
|
|
sig.OrigTtl = 14400
|
|
sig.KeyTag = 12051
|
|
sig.SignerName = "miek.nl."
|
|
sig.Signature = "oMCbslaAVIp/8kVtLSms3tDABpcPRUgHLrOR48OOplkYo+8TeEGWwkSwaz/MRo2fB4FxW0qj/hTlIjUGuACSd+b1wKdH5GvzRJc2pFmxtCbm55ygAh4EUL0F6U5cKtGJGSXxxg6UFCQ0doJCmiGFa78LolaUOXImJrk6AFrGa0M="
|
|
|
|
key := new(DNSKEY)
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 14400
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = RSASHA256
|
|
key.PublicKey = "AwEAAcNEU67LJI5GEgF9QLNqLO1SMq1EdoQ6E9f85ha0k0ewQGCblyW2836GiVsm6k8Kr5ECIoMJ6fZWf3CQSQ9ycWfTyOHfmI3eQ/1Covhb2y4bAmL/07PhrL7ozWBW3wBfM335Ft9xjtXHPy7ztCbV9qZ4TVDTW/Iyg0PiwgoXVesz"
|
|
|
|
// It should validate. Period is checked separately, so this will keep on working
|
|
if sig.Verify(key, []RR{soa}) != nil {
|
|
t.Error("failure to validate")
|
|
}
|
|
}
|
|
|
|
func TestSignature(t *testing.T) {
|
|
sig := new(RRSIG)
|
|
sig.Hdr.Name = "miek.nl."
|
|
sig.Hdr.Class = ClassINET
|
|
sig.Hdr.Ttl = 3600
|
|
sig.TypeCovered = TypeDNSKEY
|
|
sig.Algorithm = RSASHA1
|
|
sig.Labels = 2
|
|
sig.OrigTtl = 4000
|
|
sig.Expiration = 1000 //Thu Jan 1 02:06:40 CET 1970
|
|
sig.Inception = 800 //Thu Jan 1 01:13:20 CET 1970
|
|
sig.KeyTag = 34641
|
|
sig.SignerName = "miek.nl."
|
|
sig.Signature = "AwEAAaHIwpx3w4VHKi6i1LHnTaWeHCL154Jug0Rtc9ji5qwPXpBo6A5sRv7cSsPQKPIwxLpyCrbJ4mr2L0EPOdvP6z6YfljK2ZmTbogU9aSU2fiq/4wjxbdkLyoDVgtO+JsxNN4bjr4WcWhsmk1Hg93FV9ZpkWb0Tbad8DFqNDzr//kZ"
|
|
|
|
// Should not be valid
|
|
if sig.ValidityPeriod(time.Now()) {
|
|
t.Error("should not be valid")
|
|
}
|
|
|
|
sig.Inception = 315565800 //Tue Jan 1 10:10:00 CET 1980
|
|
sig.Expiration = 4102477800 //Fri Jan 1 10:10:00 CET 2100
|
|
if !sig.ValidityPeriod(time.Now()) {
|
|
t.Error("should be valid")
|
|
}
|
|
}
|
|
|
|
func TestSignVerify(t *testing.T) {
|
|
// The record we want to sign
|
|
soa := new(SOA)
|
|
soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0}
|
|
soa.Ns = "open.nlnetlabs.nl."
|
|
soa.Mbox = "miekg.atoom.net."
|
|
soa.Serial = 1293945905
|
|
soa.Refresh = 14400
|
|
soa.Retry = 3600
|
|
soa.Expire = 604800
|
|
soa.Minttl = 86400
|
|
|
|
soa1 := new(SOA)
|
|
soa1.Hdr = RR_Header{"*.miek.nl.", TypeSOA, ClassINET, 14400, 0}
|
|
soa1.Ns = "open.nlnetlabs.nl."
|
|
soa1.Mbox = "miekg.atoom.net."
|
|
soa1.Serial = 1293945905
|
|
soa1.Refresh = 14400
|
|
soa1.Retry = 3600
|
|
soa1.Expire = 604800
|
|
soa1.Minttl = 86400
|
|
|
|
srv := new(SRV)
|
|
srv.Hdr = RR_Header{"srv.miek.nl.", TypeSRV, ClassINET, 14400, 0}
|
|
srv.Port = 1000
|
|
srv.Weight = 800
|
|
srv.Target = "web1.miek.nl."
|
|
|
|
// With this key
|
|
key := new(DNSKEY)
|
|
key.Hdr.Rrtype = TypeDNSKEY
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 14400
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = RSASHA256
|
|
privkey, _ := key.Generate(512)
|
|
|
|
// Fill in the values of the Sig, before signing
|
|
sig := new(RRSIG)
|
|
sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
|
|
sig.TypeCovered = soa.Hdr.Rrtype
|
|
sig.Labels = uint8(CountLabel(soa.Hdr.Name)) // works for all 3
|
|
sig.OrigTtl = soa.Hdr.Ttl
|
|
sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
|
|
sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
|
|
sig.KeyTag = key.KeyTag() // Get the keyfrom the Key
|
|
sig.SignerName = key.Hdr.Name
|
|
sig.Algorithm = RSASHA256
|
|
|
|
for _, r := range []RR{soa, soa1, srv} {
|
|
if sig.Sign(privkey.(*rsa.PrivateKey), []RR{r}) != nil {
|
|
t.Error("failure to sign the record")
|
|
continue
|
|
}
|
|
if sig.Verify(key, []RR{r}) != nil {
|
|
t.Error("failure to validate")
|
|
continue
|
|
}
|
|
t.Logf("validated: %s", r.Header().Name)
|
|
}
|
|
}
|
|
|
|
func Test65534(t *testing.T) {
|
|
t6 := new(RFC3597)
|
|
t6.Hdr = RR_Header{"miek.nl.", 65534, ClassINET, 14400, 0}
|
|
t6.Rdata = "505D870001"
|
|
key := new(DNSKEY)
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Rrtype = TypeDNSKEY
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 14400
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = RSASHA256
|
|
privkey, _ := key.Generate(1024)
|
|
|
|
sig := new(RRSIG)
|
|
sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
|
|
sig.TypeCovered = t6.Hdr.Rrtype
|
|
sig.Labels = uint8(CountLabel(t6.Hdr.Name))
|
|
sig.OrigTtl = t6.Hdr.Ttl
|
|
sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
|
|
sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
|
|
sig.KeyTag = key.KeyTag()
|
|
sig.SignerName = key.Hdr.Name
|
|
sig.Algorithm = RSASHA256
|
|
if err := sig.Sign(privkey.(*rsa.PrivateKey), []RR{t6}); err != nil {
|
|
t.Error(err)
|
|
t.Error("failure to sign the TYPE65534 record")
|
|
}
|
|
if err := sig.Verify(key, []RR{t6}); err != nil {
|
|
t.Error(err)
|
|
t.Error("failure to validate")
|
|
} else {
|
|
t.Logf("validated: %s", t6.Header().Name)
|
|
}
|
|
}
|
|
|
|
func TestDnskey(t *testing.T) {
|
|
pubkey, err := ReadRR(strings.NewReader(`
|
|
miek.nl. IN DNSKEY 256 3 10 AwEAAZuMCu2FdugHkTrXYgl5qixvcDw1aDDlvL46/xJKbHBAHY16fNUb2b65cwko2Js/aJxUYJbZk5dwCDZxYfrfbZVtDPQuc3o8QaChVxC7/JYz2AHc9qHvqQ1j4VrH71RWINlQo6VYjzN/BGpMhOZoZOEwzp1HfsOE3lNYcoWU1smL ;{id = 5240 (zsk), size = 1024b}
|
|
`), "Kmiek.nl.+010+05240.key")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
privStr := `Private-key-format: v1.3
|
|
Algorithm: 10 (RSASHA512)
|
|
Modulus: m4wK7YV26AeROtdiCXmqLG9wPDVoMOW8vjr/EkpscEAdjXp81RvZvrlzCSjYmz9onFRgltmTl3AINnFh+t9tlW0M9C5zejxBoKFXELv8ljPYAdz2oe+pDWPhWsfvVFYg2VCjpViPM38EakyE5mhk4TDOnUd+w4TeU1hyhZTWyYs=
|
|
PublicExponent: AQAB
|
|
PrivateExponent: UfCoIQ/Z38l8vB6SSqOI/feGjHEl/fxIPX4euKf0D/32k30fHbSaNFrFOuIFmWMB3LimWVEs6u3dpbB9CQeCVg7hwU5puG7OtuiZJgDAhNeOnxvo5btp4XzPZrJSxR4WNQnwIiYWbl0aFlL1VGgHC/3By89ENZyWaZcMLW4KGWE=
|
|
Prime1: yxwC6ogAu8aVcDx2wg1V0b5M5P6jP8qkRFVMxWNTw60Vkn+ECvw6YAZZBHZPaMyRYZLzPgUlyYRd0cjupy4+fQ==
|
|
Prime2: xA1bF8M0RTIQ6+A11AoVG6GIR/aPGg5sogRkIZ7ID/sF6g9HMVU/CM2TqVEBJLRPp73cv6ZeC3bcqOCqZhz+pw==
|
|
Exponent1: xzkblyZ96bGYxTVZm2/vHMOXswod4KWIyMoOepK6B/ZPcZoIT6omLCgtypWtwHLfqyCz3MK51Nc0G2EGzg8rFQ==
|
|
Exponent2: Pu5+mCEb7T5F+kFNZhQadHUklt0JUHbi3hsEvVoHpEGSw3BGDQrtIflDde0/rbWHgDPM4WQY+hscd8UuTXrvLw==
|
|
Coefficient: UuRoNqe7YHnKmQzE6iDWKTMIWTuoqqrFAmXPmKQnC+Y+BQzOVEHUo9bXdDnoI9hzXP1gf8zENMYwYLeWpuYlFQ==
|
|
`
|
|
privkey, err := pubkey.(*DNSKEY).ReadPrivateKey(strings.NewReader(privStr),
|
|
"Kmiek.nl.+010+05240.private")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if pubkey.(*DNSKEY).PublicKey != "AwEAAZuMCu2FdugHkTrXYgl5qixvcDw1aDDlvL46/xJKbHBAHY16fNUb2b65cwko2Js/aJxUYJbZk5dwCDZxYfrfbZVtDPQuc3o8QaChVxC7/JYz2AHc9qHvqQ1j4VrH71RWINlQo6VYjzN/BGpMhOZoZOEwzp1HfsOE3lNYcoWU1smL" {
|
|
t.Error("pubkey is not what we've read")
|
|
}
|
|
if pubkey.(*DNSKEY).PrivateKeyString(privkey) != privStr {
|
|
t.Error("privkey is not what we've read")
|
|
t.Errorf("%v", pubkey.(*DNSKEY).PrivateKeyString(privkey))
|
|
}
|
|
}
|
|
|
|
func TestTag(t *testing.T) {
|
|
key := new(DNSKEY)
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Rrtype = TypeDNSKEY
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 3600
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = RSASHA256
|
|
key.PublicKey = "AwEAAcNEU67LJI5GEgF9QLNqLO1SMq1EdoQ6E9f85ha0k0ewQGCblyW2836GiVsm6k8Kr5ECIoMJ6fZWf3CQSQ9ycWfTyOHfmI3eQ/1Covhb2y4bAmL/07PhrL7ozWBW3wBfM335Ft9xjtXHPy7ztCbV9qZ4TVDTW/Iyg0PiwgoXVesz"
|
|
|
|
tag := key.KeyTag()
|
|
if tag != 12051 {
|
|
t.Errorf("wrong key tag: %d for key %v", tag, key)
|
|
}
|
|
}
|
|
|
|
func TestKeyRSA(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping test in short mode.")
|
|
}
|
|
key := new(DNSKEY)
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Rrtype = TypeDNSKEY
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 3600
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = RSASHA256
|
|
priv, _ := key.Generate(2048)
|
|
|
|
soa := new(SOA)
|
|
soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0}
|
|
soa.Ns = "open.nlnetlabs.nl."
|
|
soa.Mbox = "miekg.atoom.net."
|
|
soa.Serial = 1293945905
|
|
soa.Refresh = 14400
|
|
soa.Retry = 3600
|
|
soa.Expire = 604800
|
|
soa.Minttl = 86400
|
|
|
|
sig := new(RRSIG)
|
|
sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
|
|
sig.TypeCovered = TypeSOA
|
|
sig.Algorithm = RSASHA256
|
|
sig.Labels = 2
|
|
sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
|
|
sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
|
|
sig.OrigTtl = soa.Hdr.Ttl
|
|
sig.KeyTag = key.KeyTag()
|
|
sig.SignerName = key.Hdr.Name
|
|
|
|
if err := sig.Sign(priv.(*rsa.PrivateKey), []RR{soa}); err != nil {
|
|
t.Error("failed to sign")
|
|
return
|
|
}
|
|
if err := sig.Verify(key, []RR{soa}); err != nil {
|
|
t.Error("failed to verify")
|
|
}
|
|
}
|
|
|
|
func TestKeyToDS(t *testing.T) {
|
|
key := new(DNSKEY)
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Rrtype = TypeDNSKEY
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 3600
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = RSASHA256
|
|
key.PublicKey = "AwEAAcNEU67LJI5GEgF9QLNqLO1SMq1EdoQ6E9f85ha0k0ewQGCblyW2836GiVsm6k8Kr5ECIoMJ6fZWf3CQSQ9ycWfTyOHfmI3eQ/1Covhb2y4bAmL/07PhrL7ozWBW3wBfM335Ft9xjtXHPy7ztCbV9qZ4TVDTW/Iyg0PiwgoXVesz"
|
|
|
|
ds := key.ToDS(SHA1)
|
|
if strings.ToUpper(ds.Digest) != "B5121BDB5B8D86D0CC5FFAFBAAABE26C3E20BAC1" {
|
|
t.Errorf("wrong DS digest for SHA1\n%v", ds)
|
|
}
|
|
}
|
|
|
|
func TestSignRSA(t *testing.T) {
|
|
pub := "miek.nl. IN DNSKEY 256 3 5 AwEAAb+8lGNCxJgLS8rYVer6EnHVuIkQDghdjdtewDzU3G5R7PbMbKVRvH2Ma7pQyYceoaqWZQirSj72euPWfPxQnMy9ucCylA+FuH9cSjIcPf4PqJfdupHk9X6EBYjxrCLY4p1/yBwgyBIRJtZtAqM3ceAH2WovEJD6rTtOuHo5AluJ"
|
|
|
|
priv := `Private-key-format: v1.3
|
|
Algorithm: 5 (RSASHA1)
|
|
Modulus: v7yUY0LEmAtLythV6voScdW4iRAOCF2N217APNTcblHs9sxspVG8fYxrulDJhx6hqpZlCKtKPvZ649Z8/FCczL25wLKUD4W4f1xKMhw9/g+ol926keT1foQFiPGsItjinX/IHCDIEhEm1m0Cozdx4AfZai8QkPqtO064ejkCW4k=
|
|
PublicExponent: AQAB
|
|
PrivateExponent: YPwEmwjk5HuiROKU4xzHQ6l1hG8Iiha4cKRG3P5W2b66/EN/GUh07ZSf0UiYB67o257jUDVEgwCuPJz776zfApcCB4oGV+YDyEu7Hp/rL8KcSN0la0k2r9scKwxTp4BTJT23zyBFXsV/1wRDK1A5NxsHPDMYi2SoK63Enm/1ptk=
|
|
Prime1: /wjOG+fD0ybNoSRn7nQ79udGeR1b0YhUA5mNjDx/x2fxtIXzygYk0Rhx9QFfDy6LOBvz92gbNQlzCLz3DJt5hw==
|
|
Prime2: wHZsJ8OGhkp5p3mrJFZXMDc2mbYusDVTA+t+iRPdS797Tj0pjvU2HN4vTnTj8KBQp6hmnY7dLp9Y1qserySGbw==
|
|
Exponent1: N0A7FsSRIg+IAN8YPQqlawoTtG1t1OkJ+nWrurPootScApX6iMvn8fyvw3p2k51rv84efnzpWAYiC8SUaQDNxQ==
|
|
Exponent2: SvuYRaGyvo0zemE3oS+WRm2scxR8eiA8WJGeOc+obwOKCcBgeZblXzfdHGcEC1KaOcetOwNW/vwMA46lpLzJNw==
|
|
Coefficient: 8+7ZN/JgByqv0NfULiFKTjtyegUcijRuyij7yNxYbCBneDvZGxJwKNi4YYXWx743pcAj4Oi4Oh86gcmxLs+hGw==
|
|
Created: 20110302104537
|
|
Publish: 20110302104537
|
|
Activate: 20110302104537`
|
|
|
|
xk, _ := NewRR(pub)
|
|
k := xk.(*DNSKEY)
|
|
p, err := k.NewPrivateKey(priv)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
switch priv := p.(type) {
|
|
case *rsa.PrivateKey:
|
|
if 65537 != priv.PublicKey.E {
|
|
t.Error("exponenent should be 65537")
|
|
}
|
|
default:
|
|
t.Errorf("we should have read an RSA key: %v", priv)
|
|
}
|
|
if k.KeyTag() != 37350 {
|
|
t.Errorf("keytag should be 37350, got %d %v", k.KeyTag(), k)
|
|
}
|
|
|
|
soa := new(SOA)
|
|
soa.Hdr = RR_Header{"miek.nl.", TypeSOA, ClassINET, 14400, 0}
|
|
soa.Ns = "open.nlnetlabs.nl."
|
|
soa.Mbox = "miekg.atoom.net."
|
|
soa.Serial = 1293945905
|
|
soa.Refresh = 14400
|
|
soa.Retry = 3600
|
|
soa.Expire = 604800
|
|
soa.Minttl = 86400
|
|
|
|
sig := new(RRSIG)
|
|
sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
|
|
sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
|
|
sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
|
|
sig.KeyTag = k.KeyTag()
|
|
sig.SignerName = k.Hdr.Name
|
|
sig.Algorithm = k.Algorithm
|
|
|
|
sig.Sign(p.(*rsa.PrivateKey), []RR{soa})
|
|
if sig.Signature != "D5zsobpQcmMmYsUMLxCVEtgAdCvTu8V/IEeP4EyLBjqPJmjt96bwM9kqihsccofA5LIJ7DN91qkCORjWSTwNhzCv7bMyr2o5vBZElrlpnRzlvsFIoAZCD9xg6ZY7ZyzUJmU6IcTwG4v3xEYajcpbJJiyaw/RqR90MuRdKPiBzSo=" {
|
|
t.Errorf("signature is not correct: %v", sig)
|
|
}
|
|
}
|
|
|
|
func TestSignVerifyECDSA(t *testing.T) {
|
|
pub := `example.net. 3600 IN DNSKEY 257 3 14 (
|
|
xKYaNhWdGOfJ+nPrL8/arkwf2EY3MDJ+SErKivBVSum1
|
|
w/egsXvSADtNJhyem5RCOpgQ6K8X1DRSEkrbYQ+OB+v8
|
|
/uX45NBwY8rp65F6Glur8I/mlVNgF6W/qTI37m40 )`
|
|
priv := `Private-key-format: v1.2
|
|
Algorithm: 14 (ECDSAP384SHA384)
|
|
PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
|
|
|
|
eckey, err := NewRR(pub)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
privkey, err := eckey.(*DNSKEY).NewPrivateKey(priv)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// TODO: Create separate test for this
|
|
ds := eckey.(*DNSKEY).ToDS(SHA384)
|
|
if ds.KeyTag != 10771 {
|
|
t.Fatal("wrong keytag on DS")
|
|
}
|
|
if ds.Digest != "72d7b62976ce06438e9c0bf319013cf801f09ecc84b8d7e9495f27e305c6a9b0563a9b5f4d288405c3008a946df983d6" {
|
|
t.Fatal("wrong DS Digest")
|
|
}
|
|
a, _ := NewRR("www.example.net. 3600 IN A 192.0.2.1")
|
|
sig := new(RRSIG)
|
|
sig.Hdr = RR_Header{"example.net.", TypeRRSIG, ClassINET, 14400, 0}
|
|
sig.Expiration, _ = StringToTime("20100909102025")
|
|
sig.Inception, _ = StringToTime("20100812102025")
|
|
sig.KeyTag = eckey.(*DNSKEY).KeyTag()
|
|
sig.SignerName = eckey.(*DNSKEY).Hdr.Name
|
|
sig.Algorithm = eckey.(*DNSKEY).Algorithm
|
|
|
|
if sig.Sign(privkey.(*ecdsa.PrivateKey), []RR{a}) != nil {
|
|
t.Fatal("failure to sign the record")
|
|
}
|
|
|
|
if err := sig.Verify(eckey.(*DNSKEY), []RR{a}); err != nil {
|
|
t.Fatalf("Failure to validate:\n%s\n%s\n%s\n\n%s\n\n%v",
|
|
eckey.(*DNSKEY).String(),
|
|
a.String(),
|
|
sig.String(),
|
|
eckey.(*DNSKEY).PrivateKeyString(privkey),
|
|
err,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestSignVerifyECDSA2(t *testing.T) {
|
|
srv1, err := NewRR("srv.miek.nl. IN SRV 1000 800 0 web1.miek.nl.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
srv := srv1.(*SRV)
|
|
|
|
// With this key
|
|
key := new(DNSKEY)
|
|
key.Hdr.Rrtype = TypeDNSKEY
|
|
key.Hdr.Name = "miek.nl."
|
|
key.Hdr.Class = ClassINET
|
|
key.Hdr.Ttl = 14400
|
|
key.Flags = 256
|
|
key.Protocol = 3
|
|
key.Algorithm = ECDSAP256SHA256
|
|
privkey, err := key.Generate(256)
|
|
if err != nil {
|
|
t.Fatal("failure to generate key")
|
|
}
|
|
|
|
// Fill in the values of the Sig, before signing
|
|
sig := new(RRSIG)
|
|
sig.Hdr = RR_Header{"miek.nl.", TypeRRSIG, ClassINET, 14400, 0}
|
|
sig.TypeCovered = srv.Hdr.Rrtype
|
|
sig.Labels = uint8(CountLabel(srv.Hdr.Name)) // works for all 3
|
|
sig.OrigTtl = srv.Hdr.Ttl
|
|
sig.Expiration = 1296534305 // date -u '+%s' -d"2011-02-01 04:25:05"
|
|
sig.Inception = 1293942305 // date -u '+%s' -d"2011-01-02 04:25:05"
|
|
sig.KeyTag = key.KeyTag() // Get the keyfrom the Key
|
|
sig.SignerName = key.Hdr.Name
|
|
sig.Algorithm = ECDSAP256SHA256
|
|
|
|
if sig.Sign(privkey.(*ecdsa.PrivateKey), []RR{srv}) != nil {
|
|
t.Fatal("failure to sign the record")
|
|
}
|
|
|
|
err = sig.Verify(key, []RR{srv})
|
|
if err != nil {
|
|
t.Logf("Failure to validate:\n%s\n%s\n%s\n\n%s\n\n%v",
|
|
key.String(),
|
|
srv.String(),
|
|
sig.String(),
|
|
key.PrivateKeyString(privkey),
|
|
err,
|
|
)
|
|
}
|
|
}
|
|
|
|
// Here the test vectors from the relevant RFCs are checked.
|
|
// rfc6605 6.1
|
|
func TestRFC6605P256(t *testing.T) {
|
|
exDNSKEY := `example.net. 3600 IN DNSKEY 257 3 13 (
|
|
GojIhhXUN/u4v54ZQqGSnyhWJwaubCvTmeexv7bR6edb
|
|
krSqQpF64cYbcB7wNcP+e+MAnLr+Wi9xMWyQLc8NAA== )`
|
|
exPriv := `Private-key-format: v1.2
|
|
Algorithm: 13 (ECDSAP256SHA256)
|
|
PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=`
|
|
rrDNSKEY, err := NewRR(exDNSKEY)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
exDS := `example.net. 3600 IN DS 55648 13 2 (
|
|
b4c8c1fe2e7477127b27115656ad6256f424625bf5c1
|
|
e2770ce6d6e37df61d17 )`
|
|
rrDS, err := NewRR(exDS)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA256)
|
|
if !reflect.DeepEqual(ourDS, rrDS.(*DS)) {
|
|
t.Errorf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS))
|
|
}
|
|
|
|
exA := `www.example.net. 3600 IN A 192.0.2.1`
|
|
exRRSIG := `www.example.net. 3600 IN RRSIG A 13 3 3600 (
|
|
20100909100439 20100812100439 55648 example.net.
|
|
qx6wLYqmh+l9oCKTN6qIc+bw6ya+KJ8oMz0YP107epXA
|
|
yGmt+3SNruPFKG7tZoLBLlUzGGus7ZwmwWep666VCw== )`
|
|
rrA, err := NewRR(exA)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rrRRSIG, err := NewRR(exRRSIG)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil {
|
|
t.Errorf("Failure to validate the spec RRSIG: %v", err)
|
|
}
|
|
|
|
ourRRSIG := &RRSIG{
|
|
Hdr: RR_Header{
|
|
Ttl: rrA.Header().Ttl,
|
|
},
|
|
KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(),
|
|
SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name,
|
|
Algorithm: rrDNSKEY.(*DNSKEY).Algorithm,
|
|
}
|
|
ourRRSIG.Expiration, _ = StringToTime("20100909100439")
|
|
ourRRSIG.Inception, _ = StringToTime("20100812100439")
|
|
err = ourRRSIG.Sign(priv.(*ecdsa.PrivateKey), []RR{rrA})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil {
|
|
t.Errorf("Failure to validate our RRSIG: %v", err)
|
|
}
|
|
|
|
// Signatures are randomized
|
|
rrRRSIG.(*RRSIG).Signature = ""
|
|
ourRRSIG.Signature = ""
|
|
if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) {
|
|
t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG))
|
|
}
|
|
}
|
|
|
|
// rfc6605 6.2
|
|
func TestRFC6605P384(t *testing.T) {
|
|
exDNSKEY := `example.net. 3600 IN DNSKEY 257 3 14 (
|
|
xKYaNhWdGOfJ+nPrL8/arkwf2EY3MDJ+SErKivBVSum1
|
|
w/egsXvSADtNJhyem5RCOpgQ6K8X1DRSEkrbYQ+OB+v8
|
|
/uX45NBwY8rp65F6Glur8I/mlVNgF6W/qTI37m40 )`
|
|
exPriv := `Private-key-format: v1.2
|
|
Algorithm: 14 (ECDSAP384SHA384)
|
|
PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
|
|
rrDNSKEY, err := NewRR(exDNSKEY)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
priv, err := rrDNSKEY.(*DNSKEY).NewPrivateKey(exPriv)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
exDS := `example.net. 3600 IN DS 10771 14 4 (
|
|
72d7b62976ce06438e9c0bf319013cf801f09ecc84b8
|
|
d7e9495f27e305c6a9b0563a9b5f4d288405c3008a94
|
|
6df983d6 )`
|
|
rrDS, err := NewRR(exDS)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ourDS := rrDNSKEY.(*DNSKEY).ToDS(SHA384)
|
|
if !reflect.DeepEqual(ourDS, rrDS.(*DS)) {
|
|
t.Fatalf("DS record differs:\n%v\n%v", ourDS, rrDS.(*DS))
|
|
}
|
|
|
|
exA := `www.example.net. 3600 IN A 192.0.2.1`
|
|
exRRSIG := `www.example.net. 3600 IN RRSIG A 14 3 3600 (
|
|
20100909102025 20100812102025 10771 example.net.
|
|
/L5hDKIvGDyI1fcARX3z65qrmPsVz73QD1Mr5CEqOiLP
|
|
95hxQouuroGCeZOvzFaxsT8Glr74hbavRKayJNuydCuz
|
|
WTSSPdz7wnqXL5bdcJzusdnI0RSMROxxwGipWcJm )`
|
|
rrA, err := NewRR(exA)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rrRRSIG, err := NewRR(exRRSIG)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err = rrRRSIG.(*RRSIG).Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil {
|
|
t.Errorf("Failure to validate the spec RRSIG: %v", err)
|
|
}
|
|
|
|
ourRRSIG := &RRSIG{
|
|
Hdr: RR_Header{
|
|
Ttl: rrA.Header().Ttl,
|
|
},
|
|
KeyTag: rrDNSKEY.(*DNSKEY).KeyTag(),
|
|
SignerName: rrDNSKEY.(*DNSKEY).Hdr.Name,
|
|
Algorithm: rrDNSKEY.(*DNSKEY).Algorithm,
|
|
}
|
|
ourRRSIG.Expiration, _ = StringToTime("20100909102025")
|
|
ourRRSIG.Inception, _ = StringToTime("20100812102025")
|
|
err = ourRRSIG.Sign(priv.(*ecdsa.PrivateKey), []RR{rrA})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err = ourRRSIG.Verify(rrDNSKEY.(*DNSKEY), []RR{rrA}); err != nil {
|
|
t.Errorf("Failure to validate our RRSIG: %v", err)
|
|
}
|
|
|
|
// Signatures are randomized
|
|
rrRRSIG.(*RRSIG).Signature = ""
|
|
ourRRSIG.Signature = ""
|
|
if !reflect.DeepEqual(ourRRSIG, rrRRSIG.(*RRSIG)) {
|
|
t.Fatalf("RRSIG record differs:\n%v\n%v", ourRRSIG, rrRRSIG.(*RRSIG))
|
|
}
|
|
}
|
|
|
|
func TestInvalidRRSet(t *testing.T) {
|
|
goodRecords := make([]RR, 2)
|
|
goodRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
|
|
goodRecords[1] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"_o/"}}
|
|
|
|
// Generate key
|
|
keyname := "cloudflare.com."
|
|
key := &DNSKEY{
|
|
Hdr: RR_Header{Name: keyname, Rrtype: TypeDNSKEY, Class: ClassINET, Ttl: 0},
|
|
Algorithm: ECDSAP256SHA256,
|
|
Flags: ZONE,
|
|
Protocol: 3,
|
|
}
|
|
privatekey, err := key.Generate(256)
|
|
if err != nil {
|
|
t.Fatal(err.Error())
|
|
}
|
|
|
|
// Need to fill in: Inception, Expiration, KeyTag, SignerName and Algorithm
|
|
curTime := time.Now()
|
|
signature := &RRSIG{
|
|
Inception: uint32(curTime.Unix()),
|
|
Expiration: uint32(curTime.Add(time.Hour).Unix()),
|
|
KeyTag: key.KeyTag(),
|
|
SignerName: keyname,
|
|
Algorithm: ECDSAP256SHA256,
|
|
}
|
|
|
|
// Inconsistent name between records
|
|
badRecords := make([]RR, 2)
|
|
badRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
|
|
badRecords[1] = &TXT{Hdr: RR_Header{Name: "nama.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"_o/"}}
|
|
|
|
if IsRRset(badRecords) {
|
|
t.Fatal("Record set with inconsistent names considered valid")
|
|
}
|
|
|
|
badRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
|
|
badRecords[1] = &A{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeA, Class: ClassINET, Ttl: 0}}
|
|
|
|
if IsRRset(badRecords) {
|
|
t.Fatal("Record set with inconsistent record types considered valid")
|
|
}
|
|
|
|
badRecords[0] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
|
|
badRecords[1] = &TXT{Hdr: RR_Header{Name: "name.cloudflare.com.", Rrtype: TypeTXT, Class: ClassCHAOS, Ttl: 0}, Txt: []string{"_o/"}}
|
|
|
|
if IsRRset(badRecords) {
|
|
t.Fatal("Record set with inconsistent record class considered valid")
|
|
}
|
|
|
|
// Sign the good record set and then make sure verification fails on the bad record set
|
|
if err := signature.Sign(privatekey.(crypto.Signer), goodRecords); err != nil {
|
|
t.Fatal("Signing good records failed")
|
|
}
|
|
|
|
if err := signature.Verify(key, badRecords); err != ErrRRset {
|
|
t.Fatal("Verification did not return ErrRRset with inconsistent records")
|
|
}
|
|
}
|