From c47471f80e2b6a8db45ff75839d11417ba9fca1a Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sat, 6 Dec 2014 01:41:33 +0000 Subject: [PATCH] [DNSSEC] Make int to bytes conversions fixed length in DSA (RFC 2536) This fixes DSA key generation. --- dnssec.go | 20 ++++++++++++-------- keygen.go | 11 ++++++----- parse_test.go | 4 ++-- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/dnssec.go b/dnssec.go index 331695b9..d1c2ae62 100644 --- a/dnssec.go +++ b/dnssec.go @@ -97,6 +97,10 @@ type dnskeyWireFmt struct { /* Nothing is left out */ } +func divRoundUp(a, b int) int { + return (a + b - 1) / b +} + // KeyTag calculates the keytag (or key-id) of the DNSKEY. func (k *DNSKEY) KeyTag() uint16 { if k == nil { @@ -287,8 +291,8 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error { return err } signature := []byte{0x4D} // T value, here the ASCII M for Miek (not used in DNSSEC) - signature = append(signature, r1.Bytes()...) - signature = append(signature, s1.Bytes()...) + signature = append(signature, intToBytes(r1, 20)...) + signature = append(signature, intToBytes(s1, 20)...) rr.Signature = toBase64(signature) case *rsa.PrivateKey: // We can use nil as rand.Reader here (says AGL) @@ -635,12 +639,12 @@ func curveToBuf(_X, _Y *big.Int, intlen int) []byte { // Set the public key for X and Y for Curve. The two // values are just concatenated. func dsaToBuf(_Q, _P, _G, _Y *big.Int) []byte { - t := byte((len(_G.Bytes()) - 64) / 8) - buf := []byte{t} - buf = append(buf, _Q.Bytes()...) - buf = append(buf, _P.Bytes()...) - buf = append(buf, _G.Bytes()...) - buf = append(buf, _Y.Bytes()...) + t := divRoundUp(divRoundUp(_G.BitLen(), 8)-64, 8) + buf := []byte{byte(t)} + buf = append(buf, intToBytes(_Q, 20)...) + buf = append(buf, intToBytes(_P, 64+t*8)...) + buf = append(buf, intToBytes(_G, 64+t*8)...) + buf = append(buf, intToBytes(_Y, 64+t*8)...) return buf } diff --git a/keygen.go b/keygen.go index 80ddeb19..dfe328ec 100644 --- a/keygen.go +++ b/keygen.go @@ -139,11 +139,12 @@ func (r *DNSKEY) PrivateKeyString(p PrivateKey) (s string) { "PrivateKey: " + private + "\n" case *dsa.PrivateKey: algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + AlgorithmToString[r.Algorithm] + ")" - prime := toBase64(t.PublicKey.Parameters.P.Bytes()) - subprime := toBase64(t.PublicKey.Parameters.Q.Bytes()) - base := toBase64(t.PublicKey.Parameters.G.Bytes()) - priv := toBase64(t.X.Bytes()) - pub := toBase64(t.PublicKey.Y.Bytes()) + T := divRoundUp(divRoundUp(t.PublicKey.Parameters.G.BitLen(), 8)-64, 8) + prime := toBase64(intToBytes(t.PublicKey.Parameters.P, 64+T*8)) + subprime := toBase64(intToBytes(t.PublicKey.Parameters.Q, 20)) + base := toBase64(intToBytes(t.PublicKey.Parameters.G, 64+T*8)) + priv := toBase64(intToBytes(t.X, 20)) + pub := toBase64(intToBytes(t.PublicKey.Y, 64+T*8)) s = _FORMAT + "Algorithm: " + algorithm + "\n" + "Prime(p): " + prime + "\n" + diff --git a/parse_test.go b/parse_test.go index a667ce2f..3ff3a93e 100644 --- a/parse_test.go +++ b/parse_test.go @@ -1230,7 +1230,7 @@ type algorithm struct { bits int } -func TestNewPrivateKeyECDSA(t *testing.T) { +func TestNewPrivateKey(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } @@ -1239,7 +1239,7 @@ func TestNewPrivateKeyECDSA(t *testing.T) { algorithm{ECDSAP384SHA384, 384}, algorithm{RSASHA1, 1024}, algorithm{RSASHA256, 2048}, - // algorithm{DSA, 1024}, // TODO: STILL BROKEN! + algorithm{DSA, 1024}, } for _, algo := range algorithms {