From 54f158c23d6fd505e32d39ff056d2bf8203c224b Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Sat, 15 Jan 2011 10:38:14 +0100 Subject: [PATCH] Helper functions for base64 encoding/decoding --- dnssec.go | 22 +++++++++------------- keygen.go | 14 +++++--------- msg.go | 35 ++++++++++++++++++++++++++--------- 3 files changed, 40 insertions(+), 31 deletions(-) diff --git a/dnssec.go b/dnssec.go index 9251ef4d..098f221b 100644 --- a/dnssec.go +++ b/dnssec.go @@ -8,7 +8,6 @@ import ( "crypto/rsa" "crypto/rand" "encoding/hex" - "encoding/base64" "hash" "time" "io" @@ -260,9 +259,7 @@ func (s *RR_RRSIG) Sign(k PrivateKey, rrset RRset) bool { if err != nil { return false } - b64 := make([]byte, base64.StdEncoding.EncodedLen(len(signature))) - base64.StdEncoding.Encode(b64, signature) - s.Signature = string(b64) + s.Signature = unpackBase64(signature) default: // Not given the correct key return false @@ -410,20 +407,19 @@ func (s *RR_RRSIG) PeriodOK() bool { // Return the signatures base64 encodedig sigdata as a byte slice. func (s *RR_RRSIG) sigBuf() []byte { - sigbuf := make([]byte, 1024) // TODO(mg) length! - sigbuflen := base64.StdEncoding.DecodedLen(len(s.Signature)) - sigbuflen, _ = base64.StdEncoding.Decode(sigbuf[0:sigbuflen], []byte(s.Signature)) - sigbuf = sigbuf[:sigbuflen] + sigbuf, err := packBase64([]byte(s.Signature)) + if err != nil { + return nil + } return sigbuf } // Extract the RSA public key from the Key record func (k *RR_DNSKEY) pubKeyRSA() *rsa.PublicKey { - // 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] + keybuf, err := packBase64([]byte(k.PubKey)) + if err != nil { + return nil + } // RFC 2537/3110, section 2. RSA Public KEY Resource Records // Length is in the 0th byte, unless its zero, then it diff --git a/keygen.go b/keygen.go index e27d2a0d..0bd3e72c 100644 --- a/keygen.go +++ b/keygen.go @@ -4,11 +4,10 @@ import ( "os" "crypto/rsa" "crypto/rand" - "encoding/base64" ) -// Empty interface so all crypty private key -// can be grouped together +// Empty interface that is used a wrapper around all possible +// private key implementation from the crypto package. type PrivateKey interface{} // io.Reader @@ -16,10 +15,10 @@ type PrivateKey interface{} // PrivateKeyFromString // PrivateKeyToDNSKEY -// Generate a Key of the given bit size. +// Generate a key of the given bit size. // The public part is directly put inside the DNSKEY record. // The Algorithm in the key must be set as this will define -// what kind of DNSKEY will be generated +// what kind of DNSKEY will be generated. func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error) { switch r.Algorithm { case AlgRSAMD5, AlgRSASHA1, AlgRSASHA256: @@ -56,10 +55,7 @@ func (r *RR_DNSKEY) Generate(bits int) (PrivateKey, os.Error) { return nil, &Error{Error: "Exponent too large"} } keybuf = append(keybuf, priv.PublicKey.N.Bytes()...) - - b64 := make([]byte, base64.StdEncoding.EncodedLen(len(keybuf))) - base64.StdEncoding.Encode(b64, keybuf) - r.PubKey = string(b64) + r.PubKey = unpackBase64(keybuf) return priv, nil } return nil, nil // Dummy return diff --git a/msg.go b/msg.go index 9949031d..cbee9fdd 100644 --- a/msg.go +++ b/msg.go @@ -286,10 +286,10 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o msg[off] = byte(fv.Elem(j).(*reflect.UintValue).Get()) off++ } - case "NSEC": // NSEC/NSEC3 + case "NSEC": // NSEC/NSEC3 for j := 0; j < val.Field(i).(*reflect.SliceValue).Len(); j++ { - var _ = byte(fv.Elem(j).(*reflect.UintValue).Get()) - } + var _ = byte(fv.Elem(j).(*reflect.UintValue).Get()) + } // handle type bit maps } case *reflect.StructValue: @@ -342,7 +342,7 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o default: return len(msg), false case "base64": - // TODO(mg) use the Len as return from the conversion (not used right now) + // TODO(mg) use the Len as return from the conversion (not used right now) b64len := base64.StdEncoding.DecodedLen(len(s)) _, err := base64.StdEncoding.Decode(msg[off:off+b64len], []byte(s)) if err != nil { @@ -559,10 +559,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, default: consumed = 0 // TODO } - // TODO(mg) check return value of encoding - b64 := make([]byte, base64.StdEncoding.EncodedLen(len(msg[off:off+rdlength-consumed]))) - base64.StdEncoding.Encode(b64, msg[off:off+rdlength-consumed]) - s = string(b64) + s = unpackBase64(msg[off : off+rdlength-consumed]) off += rdlength - consumed case "domain-name": s, off, ok = unpackDomainName(msg, off) @@ -600,6 +597,24 @@ func unpackStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) { return off, ok } +func unpackBase64(b []byte) string { + b64 := make([]byte, base64.StdEncoding.EncodedLen(len(b))) + base64.StdEncoding.Encode(b64, b) + return string(b64) +} + +// Helper function for packing, mostly used in dnssec.go +func packBase64(s []byte) ([]byte, os.Error) { + b64len := base64.StdEncoding.DecodedLen(len(s)) + buf := make([]byte, b64len) + n, err := base64.StdEncoding.Decode(buf, []byte(s)) + if err != nil { + return nil, err + } + buf = buf[:n] + return buf, nil +} + // Resource record packer. func packRR(rr RR, msg []byte, off int) (off2 int, ok bool) { if rr == nil { @@ -696,6 +711,7 @@ func (h *MsgHdr) String() string { return s } +// Pack a msg: convert it to wire format. func (dns *Msg) Pack() (msg []byte, ok bool) { var dh Header @@ -764,6 +780,7 @@ func (dns *Msg) Pack() (msg []byte, ok bool) { return msg[:off], true } +// Unpack a binary message to a Msg structure. func (dns *Msg) Unpack(msg []byte) bool { // Header. var dh Header @@ -808,7 +825,7 @@ func (dns *Msg) Unpack(msg []byte) bool { return true } -// Convert a complete message to a string, use dig-like output. +// Convert a complete message to a string using dig-like output. func (dns *Msg) String() string { if dns == nil { return " MsgHdr"