Refactor DNSSEC to use crypto.{PrivateKey,Signer}

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.
This commit is contained in:
Filippo Valsorda 2015-03-26 15:34:52 -07:00
parent c50a9fc91d
commit 034c247229
8 changed files with 234 additions and 271 deletions

237
dnssec.go
View File

@ -6,14 +6,14 @@ import (
"crypto/dsa"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/md5"
_ "crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
_ "crypto/sha1"
_ "crypto/sha256"
_ "crypto/sha512"
"encoding/asn1"
"encoding/hex"
"hash"
"io"
"math/big"
"sort"
"strings"
@ -42,6 +42,38 @@ const (
PRIVATEOID uint8 = 254
)
// Map for algorithm names.
var AlgorithmToString = map[uint8]string{
RSAMD5: "RSAMD5",
DH: "DH",
DSA: "DSA",
RSASHA1: "RSASHA1",
DSANSEC3SHA1: "DSA-NSEC3-SHA1",
RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
RSASHA256: "RSASHA256",
RSASHA512: "RSASHA512",
ECCGOST: "ECC-GOST",
ECDSAP256SHA256: "ECDSAP256SHA256",
ECDSAP384SHA384: "ECDSAP384SHA384",
INDIRECT: "INDIRECT",
PRIVATEDNS: "PRIVATEDNS",
PRIVATEOID: "PRIVATEOID",
}
// Map of algorithm strings.
var StringToAlgorithm = reverseInt8(AlgorithmToString)
// Map of algorithm crypto hashes.
var AlgorithmToHash = map[uint8]crypto.Hash{
RSAMD5: crypto.MD5, // Deprecated in RFC 6725
RSASHA1: crypto.SHA1,
RSASHA1NSEC3SHA1: crypto.SHA1,
RSASHA256: crypto.SHA256,
ECDSAP256SHA256: crypto.SHA256,
ECDSAP384SHA384: crypto.SHA384,
RSASHA512: crypto.SHA512,
}
// DNSSEC hashing algorithm codes.
const (
_ uint8 = iota
@ -52,6 +84,18 @@ const (
SHA512 // Experimental
)
// Map for hash names.
var HashToString = map[uint8]string{
SHA1: "SHA1",
SHA256: "SHA256",
GOST94: "GOST94",
SHA384: "SHA384",
SHA512: "SHA512",
}
// Map of hash strings.
var StringToHash = reverseInt8(HashToString)
// DNSKEY flag values.
const (
SEP = 1
@ -168,24 +212,23 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
// digest buffer
digest := append(owner, wire...) // another copy
var hash crypto.Hash
switch h {
case SHA1:
s := sha1.New()
io.WriteString(s, string(digest))
ds.Digest = hex.EncodeToString(s.Sum(nil))
hash = crypto.SHA1
case SHA256:
s := sha256.New()
io.WriteString(s, string(digest))
ds.Digest = hex.EncodeToString(s.Sum(nil))
hash = crypto.SHA256
case SHA384:
s := sha512.New384()
io.WriteString(s, string(digest))
ds.Digest = hex.EncodeToString(s.Sum(nil))
case GOST94:
/* I have no clue */
hash = crypto.SHA384
case SHA512:
hash = crypto.SHA512
default:
return nil
}
s := hash.New()
s.Write(digest)
ds.Digest = hex.EncodeToString(s.Sum(nil))
return ds
}
@ -212,7 +255,7 @@ func (d *DS) ToCDS() *CDS {
// There is no check if RRSet is a proper (RFC 2181) RRSet.
// If OrigTTL is non zero, it is used as-is, otherwise the TTL of the RRset
// is used as the OrigTTL.
func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
if k == nil {
return ErrPrivKey
}
@ -258,39 +301,66 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
}
signdata = append(signdata, wire...)
var h hash.Hash
switch rr.Algorithm {
case DSA, DSANSEC3SHA1:
// TODO: this seems bugged, will panic
case RSASHA1, RSASHA1NSEC3SHA1:
h = sha1.New()
case RSASHA256, ECDSAP256SHA256:
h = sha256.New()
case ECDSAP384SHA384:
h = sha512.New384()
case RSASHA512:
h = sha512.New()
case RSAMD5:
fallthrough // Deprecated in RFC 6725
default:
hash, ok := AlgorithmToHash[rr.Algorithm]
if !ok {
return ErrAlg
}
_, err = h.Write(signdata)
if err != nil {
return err
}
sighash := h.Sum(nil)
h := hash.New()
h.Write(signdata)
signature, err := k.Sign(sighash, rr.Algorithm)
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
if err != nil {
return err
}
rr.Signature = toBase64(signature)
return nil
}
func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
signature, err := k.Sign(rand.Reader, hashed, hash)
if err != nil {
return nil, err
}
switch alg {
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
return signature, nil
case ECDSAP256SHA256, ECDSAP384SHA384:
ecdsaSignature := &struct {
R, S *big.Int
}{}
if _, err := asn1.Unmarshal(signature, ecdsaSignature); err != nil {
return nil, err
}
var intlen int
switch alg {
case ECDSAP256SHA256:
intlen = 32
case ECDSAP384SHA384:
intlen = 48
}
signature := intToBytes(ecdsaSignature.R, intlen)
signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
return signature, nil
// There is no defined interface for what a DSA backed crypto.Signer returns
case DSA, DSANSEC3SHA1:
// t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
// signature := []byte{byte(t)}
// signature = append(signature, intToBytes(r1, 20)...)
// signature = append(signature, intToBytes(s1, 20)...)
// rr.Signature = signature
}
return nil, ErrAlg
}
// Verify validates an RRSet with the signature and key. This is only the
// cryptographic test, the signature validity period must be checked separately.
// This function copies the rdata of some RRs (to lowercase domain names) for the validation to work.
@ -355,6 +425,11 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
// remove the domain name and assume its our
}
hash, ok := AlgorithmToHash[rr.Algorithm]
if !ok {
return ErrAlg
}
switch rr.Algorithm {
case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, RSAMD5:
// TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere??
@ -362,52 +437,31 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
if pubkey == nil {
return ErrKey
}
// Setup the hash as defined for this alg.
var h hash.Hash
var ch crypto.Hash
switch rr.Algorithm {
case RSAMD5:
h = md5.New()
ch = crypto.MD5
case RSASHA1, RSASHA1NSEC3SHA1:
h = sha1.New()
ch = crypto.SHA1
case RSASHA256:
h = sha256.New()
ch = crypto.SHA256
case RSASHA512:
h = sha512.New()
ch = crypto.SHA512
}
io.WriteString(h, string(signeddata))
sighash := h.Sum(nil)
return rsa.VerifyPKCS1v15(pubkey, ch, sighash, sigbuf)
h := hash.New()
h.Write(signeddata)
return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
case ECDSAP256SHA256, ECDSAP384SHA384:
pubkey := k.publicKeyECDSA()
if pubkey == nil {
return ErrKey
}
var h hash.Hash
switch rr.Algorithm {
case ECDSAP256SHA256:
h = sha256.New()
case ECDSAP384SHA384:
h = sha512.New384()
}
io.WriteString(h, string(signeddata))
sighash := h.Sum(nil)
// Split sigbuf into the r and s coordinates
r := big.NewInt(0)
r.SetBytes(sigbuf[:len(sigbuf)/2])
s := big.NewInt(0)
s.SetBytes(sigbuf[len(sigbuf)/2:])
if ecdsa.Verify(pubkey, sighash, r, s) {
r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2])
s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:])
h := hash.New()
h.Write(signeddata)
if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
return nil
}
return ErrSig
default:
return ErrAlg
}
// Unknown alg
return ErrAlg
}
// ValidityPeriod uses RFC1982 serial arithmetic to calculate
@ -603,36 +657,3 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
}
return buf, nil
}
// Map for algorithm names.
var AlgorithmToString = map[uint8]string{
RSAMD5: "RSAMD5",
DH: "DH",
DSA: "DSA",
RSASHA1: "RSASHA1",
DSANSEC3SHA1: "DSA-NSEC3-SHA1",
RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1",
RSASHA256: "RSASHA256",
RSASHA512: "RSASHA512",
ECCGOST: "ECC-GOST",
ECDSAP256SHA256: "ECDSAP256SHA256",
ECDSAP384SHA384: "ECDSAP384SHA384",
INDIRECT: "INDIRECT",
PRIVATEDNS: "PRIVATEDNS",
PRIVATEOID: "PRIVATEOID",
}
// Map of algorithm strings.
var StringToAlgorithm = reverseInt8(AlgorithmToString)
// Map for hash names.
var HashToString = map[uint8]string{
SHA1: "SHA1",
SHA256: "SHA256",
GOST94: "GOST94",
SHA384: "SHA384",
SHA512: "SHA512",
}
// Map of hash strings.
var StringToHash = reverseInt8(HashToString)

View File

@ -1,6 +1,7 @@
package dns
import (
"crypto"
"crypto/dsa"
"crypto/ecdsa"
"crypto/elliptic"
@ -15,7 +16,7 @@ import (
// what kind of DNSKEY will be generated.
// The ECDSA algorithms imply a fixed keysize, in that case
// bits should be set to the size of the algorithm.
func (k *DNSKEY) Generate(bits int) (PrivateKey, error) {
func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
switch k.Algorithm {
case DSA, DSANSEC3SHA1:
if bits != 1024 {
@ -52,14 +53,14 @@ func (k *DNSKEY) Generate(bits int) (PrivateKey, error) {
return nil, err
}
k.setPublicKeyDSA(params.Q, params.P, params.G, priv.PublicKey.Y)
return (*DSAPrivateKey)(priv), nil
return priv, nil
case RSAMD5, RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1:
priv, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, err
}
k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N)
return (*RSAPrivateKey)(priv), nil
return priv, nil
case ECDSAP256SHA256, ECDSAP384SHA384:
var c elliptic.Curve
switch k.Algorithm {
@ -73,7 +74,7 @@ func (k *DNSKEY) Generate(bits int) (PrivateKey, error) {
return nil, err
}
k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
return (*ECDSAPrivateKey)(priv), nil
return priv, nil
default:
return nil, ErrAlg
}

View File

@ -1,6 +1,7 @@
package dns
import (
"crypto"
"crypto/dsa"
"crypto/ecdsa"
"crypto/rsa"
@ -12,7 +13,7 @@ import (
// NewPrivateKey returns a PrivateKey by parsing the string s.
// s should be in the same form of the BIND private key files.
func (k *DNSKEY) NewPrivateKey(s string) (PrivateKey, error) {
func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
if s[len(s)-1] != '\n' { // We need a closing newline
return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
}
@ -23,7 +24,7 @@ func (k *DNSKEY) NewPrivateKey(s string) (PrivateKey, error) {
// only used in error reporting.
// The public key must be known, because some cryptographic algorithms embed
// the public inside the privatekey.
func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
m, e := parseKey(q, file)
if m == nil {
return nil, e
@ -50,7 +51,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
return nil, ErrKey
}
priv.PublicKey = *pub
return (*DSAPrivateKey)(priv), e
return priv, e
case RSAMD5:
fallthrough
case RSASHA1:
@ -69,7 +70,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
return nil, ErrKey
}
priv.PublicKey = *pub
return (*RSAPrivateKey)(priv), e
return priv, e
case ECCGOST:
return nil, ErrPrivKey
case ECDSAP256SHA256:
@ -84,7 +85,7 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (PrivateKey, error) {
return nil, ErrKey
}
priv.PublicKey = *pub
return (*ECDSAPrivateKey)(priv), e
return priv, e
default:
return nil, ErrPrivKey
}

View File

@ -4,7 +4,6 @@ import (
"crypto"
"crypto/dsa"
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"math/big"
"strconv"
@ -12,133 +11,75 @@ import (
const format = "Private-key-format: v1.3\n"
// PrivateKey ... TODO(miek)
type PrivateKey interface {
Sign([]byte, uint8) ([]byte, error)
String(uint8) string
}
// PrivateKeyString converts a PrivateKey to a string. This string has the same
// format as the private-key-file of BIND9 (Private-key-format: v1.3).
// It needs some info from the key (the algorithm), so its a method of the
// DNSKEY and calls PrivateKey.String(alg).
func (r *DNSKEY) PrivateKeyString(p PrivateKey) string {
return p.String(r.Algorithm)
}
// It needs some info from the key (the algorithm), so its a method of the DNSKEY
// It supports rsa.PrivateKey, ecdsa.PrivateKey and dsa.PrivateKey
func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
algorithm := strconv.Itoa(int(r.Algorithm))
algorithm += " (" + AlgorithmToString[r.Algorithm] + ")"
type RSAPrivateKey rsa.PrivateKey
switch p := p.(type) {
case *rsa.PrivateKey:
modulus := toBase64(p.PublicKey.N.Bytes())
e := big.NewInt(int64(p.PublicKey.E))
publicExponent := toBase64(e.Bytes())
privateExponent := toBase64(p.D.Bytes())
prime1 := toBase64(p.Primes[0].Bytes())
prime2 := toBase64(p.Primes[1].Bytes())
// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
// and from: http://code.google.com/p/go/issues/detail?id=987
one := big.NewInt(1)
p1 := big.NewInt(0).Sub(p.Primes[0], one)
q1 := big.NewInt(0).Sub(p.Primes[1], one)
exp1 := big.NewInt(0).Mod(p.D, p1)
exp2 := big.NewInt(0).Mod(p.D, q1)
coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
exponent1 := toBase64(exp1.Bytes())
exponent2 := toBase64(exp2.Bytes())
coefficient := toBase64(coeff.Bytes())
return format +
"Algorithm: " + algorithm + "\n" +
"Modulus: " + modulus + "\n" +
"PublicExponent: " + publicExponent + "\n" +
"PrivateExponent: " + privateExponent + "\n" +
"Prime1: " + prime1 + "\n" +
"Prime2: " + prime2 + "\n" +
"Exponent1: " + exponent1 + "\n" +
"Exponent2: " + exponent2 + "\n" +
"Coefficient: " + coefficient + "\n"
case *ecdsa.PrivateKey:
var intlen int
switch r.Algorithm {
case ECDSAP256SHA256:
intlen = 32
case ECDSAP384SHA384:
intlen = 48
}
private := toBase64(intToBytes(p.D, intlen))
return format +
"Algorithm: " + algorithm + "\n" +
"PrivateKey: " + private + "\n"
case *dsa.PrivateKey:
T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8)
prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8))
subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20))
base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8))
priv := toBase64(intToBytes(p.X, 20))
pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8))
return format +
"Algorithm: " + algorithm + "\n" +
"Prime(p): " + prime + "\n" +
"Subprime(q): " + subprime + "\n" +
"Base(g): " + base + "\n" +
"Private_value(x): " + priv + "\n" +
"Public_value(y): " + pub + "\n"
func (p *RSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) {
var hash crypto.Hash
switch alg {
case RSASHA1, RSASHA1NSEC3SHA1:
hash = crypto.SHA1
case RSASHA256:
hash = crypto.SHA256
case RSASHA512:
hash = crypto.SHA512
default:
return nil, ErrAlg
return ""
}
return rsa.SignPKCS1v15(nil, (*rsa.PrivateKey)(p), hash, hashed)
}
func (p *RSAPrivateKey) String(alg uint8) string {
algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")"
modulus := toBase64(p.PublicKey.N.Bytes())
e := big.NewInt(int64(p.PublicKey.E))
publicExponent := toBase64(e.Bytes())
privateExponent := toBase64(p.D.Bytes())
prime1 := toBase64(p.Primes[0].Bytes())
prime2 := toBase64(p.Primes[1].Bytes())
// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
// and from: http://code.google.com/p/go/issues/detail?id=987
one := big.NewInt(1)
p1 := big.NewInt(0).Sub(p.Primes[0], one)
q1 := big.NewInt(0).Sub(p.Primes[1], one)
exp1 := big.NewInt(0).Mod(p.D, p1)
exp2 := big.NewInt(0).Mod(p.D, q1)
coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
exponent1 := toBase64(exp1.Bytes())
exponent2 := toBase64(exp2.Bytes())
coefficient := toBase64(coeff.Bytes())
return format +
"Algorithm: " + algorithm + "\n" +
"Modulus: " + modulus + "\n" +
"PublicExponent: " + publicExponent + "\n" +
"PrivateExponent: " + privateExponent + "\n" +
"Prime1: " + prime1 + "\n" +
"Prime2: " + prime2 + "\n" +
"Exponent1: " + exponent1 + "\n" +
"Exponent2: " + exponent2 + "\n" +
"Coefficient: " + coefficient + "\n"
}
type ECDSAPrivateKey ecdsa.PrivateKey
func (p *ECDSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) {
var intlen int
switch alg {
case ECDSAP256SHA256:
intlen = 32
case ECDSAP384SHA384:
intlen = 48
default:
return nil, ErrAlg
}
r1, s1, err := ecdsa.Sign(rand.Reader, (*ecdsa.PrivateKey)(p), hashed)
if err != nil {
return nil, err
}
signature := intToBytes(r1, intlen)
signature = append(signature, intToBytes(s1, intlen)...)
return signature, nil
}
func (p *ECDSAPrivateKey) String(alg uint8) string {
algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")"
var intlen int
switch alg {
case ECDSAP256SHA256:
intlen = 32
case ECDSAP384SHA384:
intlen = 48
}
private := toBase64(intToBytes(p.D, intlen))
return format +
"Algorithm: " + algorithm + "\n" +
"PrivateKey: " + private + "\n"
}
type DSAPrivateKey dsa.PrivateKey
func (p *DSAPrivateKey) Sign(hashed []byte, alg uint8) ([]byte, error) {
r1, s1, err := dsa.Sign(rand.Reader, (*dsa.PrivateKey)(p), hashed)
if err != nil {
return nil, err
}
t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
signature := []byte{byte(t)}
signature = append(signature, intToBytes(r1, 20)...)
signature = append(signature, intToBytes(s1, 20)...)
return signature, nil
}
func (p *DSAPrivateKey) String(alg uint8) string {
algorithm := strconv.Itoa(int(alg)) + " (" + AlgorithmToString[alg] + ")"
T := divRoundUp(divRoundUp(p.PublicKey.Parameters.G.BitLen(), 8)-64, 8)
prime := toBase64(intToBytes(p.PublicKey.Parameters.P, 64+T*8))
subprime := toBase64(intToBytes(p.PublicKey.Parameters.Q, 20))
base := toBase64(intToBytes(p.PublicKey.Parameters.G, 64+T*8))
priv := toBase64(intToBytes(p.X, 20))
pub := toBase64(intToBytes(p.PublicKey.Y, 64+T*8))
return format +
"Algorithm: " + algorithm + "\n" +
"Prime(p): " + prime + "\n" +
"Subprime(q): " + subprime + "\n" +
"Base(g): " + base + "\n" +
"Private_value(x): " + priv + "\n" +
"Public_value(y): " + pub + "\n"
}

View File

@ -1,6 +1,9 @@
package dns
import (
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"reflect"
"strings"
"testing"
@ -192,7 +195,7 @@ func TestSignVerify(t *testing.T) {
sig.Algorithm = RSASHA256
for _, r := range []RR{soa, soa1, srv} {
if sig.Sign(privkey, []RR{r}) != nil {
if sig.Sign(privkey.(*rsa.PrivateKey), []RR{r}) != nil {
t.Error("failure to sign the record")
continue
}
@ -228,7 +231,7 @@ func Test65534(t *testing.T) {
sig.KeyTag = key.KeyTag()
sig.SignerName = key.Hdr.Name
sig.Algorithm = RSASHA256
if err := sig.Sign(privkey, []RR{t6}); err != nil {
if err := sig.Sign(privkey.(*rsa.PrivateKey), []RR{t6}); err != nil {
t.Error(err)
t.Error("failure to sign the TYPE65534 record")
}
@ -324,7 +327,7 @@ func TestKeyRSA(t *testing.T) {
sig.KeyTag = key.KeyTag()
sig.SignerName = key.Hdr.Name
if err := sig.Sign(priv, []RR{soa}); err != nil {
if err := sig.Sign(priv.(*rsa.PrivateKey), []RR{soa}); err != nil {
t.Error("failed to sign")
return
}
@ -374,7 +377,7 @@ Activate: 20110302104537`
t.Error(err)
}
switch priv := p.(type) {
case *RSAPrivateKey:
case *rsa.PrivateKey:
if 65537 != priv.PublicKey.E {
t.Error("exponenent should be 65537")
}
@ -403,7 +406,7 @@ Activate: 20110302104537`
sig.SignerName = k.Hdr.Name
sig.Algorithm = k.Algorithm
sig.Sign(p, []RR{soa})
sig.Sign(p.(*rsa.PrivateKey), []RR{soa})
if sig.Signature != "D5zsobpQcmMmYsUMLxCVEtgAdCvTu8V/IEeP4EyLBjqPJmjt96bwM9kqihsccofA5LIJ7DN91qkCORjWSTwNhzCv7bMyr2o5vBZElrlpnRzlvsFIoAZCD9xg6ZY7ZyzUJmU6IcTwG4v3xEYajcpbJJiyaw/RqR90MuRdKPiBzSo=" {
t.Errorf("signature is not correct: %v", sig)
}
@ -443,7 +446,7 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
sig.SignerName = eckey.(*DNSKEY).Hdr.Name
sig.Algorithm = eckey.(*DNSKEY).Algorithm
if sig.Sign(privkey, []RR{a}) != nil {
if sig.Sign(privkey.(*ecdsa.PrivateKey), []RR{a}) != nil {
t.Fatal("failure to sign the record")
}
@ -491,7 +494,7 @@ func TestSignVerifyECDSA2(t *testing.T) {
sig.SignerName = key.Hdr.Name
sig.Algorithm = ECDSAP256SHA256
if sig.Sign(privkey, []RR{srv}) != nil {
if sig.Sign(privkey.(*ecdsa.PrivateKey), []RR{srv}) != nil {
t.Fatal("failure to sign the record")
}
@ -564,7 +567,7 @@ PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=`
}
ourRRSIG.Expiration, _ = StringToTime("20100909100439")
ourRRSIG.Inception, _ = StringToTime("20100812100439")
err = ourRRSIG.Sign(priv, []RR{rrA})
err = ourRRSIG.Sign(priv.(*ecdsa.PrivateKey), []RR{rrA})
if err != nil {
t.Fatal(err)
}
@ -640,7 +643,7 @@ PrivateKey: WURgWHCcYIYUPWgeLmiPY2DJJk02vgrmTfitxgqcL4vwW7BOrbawVmVe0d9V94SR`
}
ourRRSIG.Expiration, _ = StringToTime("20100909102025")
ourRRSIG.Inception, _ = StringToTime("20100812102025")
err = ourRRSIG.Sign(priv, []RR{rrA})
err = ourRRSIG.Sign(priv.(*ecdsa.PrivateKey), []RR{rrA})
if err != nil {
t.Fatal(err)
}
@ -709,7 +712,7 @@ func TestInvalidRRSet(t *testing.T) {
}
// Sign the good record set and then make sure verification fails on the bad record set
if err := signature.Sign(privatekey, goodRecords); err != nil {
if err := signature.Sign(privatekey.(crypto.Signer), goodRecords); err != nil {
t.Fatal("Signing good records failed")
}

View File

@ -1237,8 +1237,8 @@ func TestNewPrivateKey(t *testing.T) {
}
switch newPrivKey := newPrivKey.(type) {
case *RSAPrivateKey:
(*rsa.PrivateKey)(newPrivKey).Precompute()
case *rsa.PrivateKey:
newPrivKey.Precompute()
}
if !reflect.DeepEqual(privkey, newPrivKey) {

25
sig0.go
View File

@ -13,7 +13,7 @@ import (
// Sign signs a dns.Msg. It fills the signature with the appropriate data.
// The SIG record should have the SignerName, KeyTag, Algorithm, Inception
// and Expiration set.
func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
if k == nil {
return nil, ErrPrivKey
}
@ -41,31 +41,26 @@ func (rr *SIG) Sign(k PrivateKey, m *Msg) ([]byte, error) {
return nil, err
}
buf = buf[:off:cap(buf)]
var hash crypto.Hash
switch rr.Algorithm {
case DSA, RSASHA1:
hash = crypto.SHA1
case RSASHA256, ECDSAP256SHA256:
hash = crypto.SHA256
case ECDSAP384SHA384:
hash = crypto.SHA384
case RSASHA512:
hash = crypto.SHA512
default:
hash, ok := AlgorithmToHash[rr.Algorithm]
if !ok {
return nil, ErrAlg
}
hasher := hash.New()
// Write SIG rdata
hasher.Write(buf[len(mbuf)+1+2+2+4+2:])
// Write message
hasher.Write(buf[:len(mbuf)])
hashed := hasher.Sum(nil)
sig, err := k.Sign(hashed, rr.Algorithm)
signature, err := sign(k, hasher.Sum(nil), hash, rr.Algorithm)
if err != nil {
return nil, err
}
rr.Signature = toBase64(sig)
rr.Signature = toBase64(signature)
sig := string(signature)
buf = append(buf, sig...)
if len(buf) > int(^uint16(0)) {
return nil, ErrBuf

View File

@ -1,6 +1,7 @@
package dns
import (
"crypto"
"testing"
"time"
)
@ -11,7 +12,7 @@ func TestSIG0(t *testing.T) {
}
m := new(Msg)
m.SetQuestion("example.org.", TypeSOA)
for _, alg := range []uint8{DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256, RSASHA512} {
for _, alg := range []uint8{ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256, RSASHA512} {
algstr := AlgorithmToString[alg]
keyrr := new(KEY)
keyrr.Hdr.Name = algstr + "."
@ -40,7 +41,7 @@ func TestSIG0(t *testing.T) {
sigrr.Inception = now - 300
sigrr.KeyTag = keyrr.KeyTag()
sigrr.SignerName = keyrr.Hdr.Name
mb, err := sigrr.Sign(pk, m)
mb, err := sigrr.Sign(pk.(crypto.Signer), m)
if err != nil {
t.Errorf("Failed to sign message using “%s”: %v", algstr, err)
continue
@ -79,7 +80,7 @@ func TestSIG0(t *testing.T) {
}
sigrr.Expiration = 2
sigrr.Inception = 1
mb, _ = sigrr.Sign(pk, m)
mb, _ = sigrr.Sign(pk.(crypto.Signer), m)
if err := sigrr.Verify(keyrr, mb); err == nil {
t.Errorf("Verify succeeded on an expired message using “%s”", algstr)
continue