[DNSSEC] Make int to bytes conversions fixed length in ECDSA

ECDSA public keys consist of a single value, called "Q" in FIPS
  186-3.  In DNSSEC keys, Q is a simple bit string that represents the
  uncompressed form of a curve point, "x | y".

  The ECDSA signature is the combination of two non-negative integers,
  called "r" and "s" in FIPS 186-3.  The two integers, each of which is
  formatted as a simple octet string, are combined into a single longer
  octet string for DNSSEC as the concatenation "r | s".  (Conversion of
  the integers to bit strings is described in Section C.2 of FIPS
  186-3.)  For P-256, each integer MUST be encoded as 32 octets; for
  P-384, each integer MUST be encoded as 48 octets.
This commit is contained in:
Filippo Valsorda 2014-12-05 20:16:13 +00:00
parent 0f1b1184ae
commit ed475ae9fa
3 changed files with 35 additions and 9 deletions

View File

@ -255,6 +255,7 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
var sighash []byte
var h hash.Hash
var ch crypto.Hash // Only need for RSA
var intlen int
switch rr.Algorithm {
case DSA, DSANSEC3SHA1:
// Implicit in the ParameterSizes
@ -264,8 +265,10 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
case RSASHA256, ECDSAP256SHA256:
h = sha256.New()
ch = crypto.SHA256
intlen = 32
case ECDSAP384SHA384:
h = sha512.New384()
intlen = 48
case RSASHA512:
h = sha512.New()
ch = crypto.SHA512
@ -299,8 +302,8 @@ func (rr *RRSIG) Sign(k PrivateKey, rrset []RR) error {
if err != nil {
return err
}
signature := r1.Bytes()
signature = append(signature, s1.Bytes()...)
signature := intToBytes(r1, intlen)
signature = append(signature, intToBytes(s1, intlen)...)
rr.Signature = toBase64(signature)
default:
// Not given the correct key
@ -582,9 +585,14 @@ func (k *DNSKEY) setPublicKeyCurve(_X, _Y *big.Int) bool {
if _X == nil || _Y == nil {
return false
}
buf := curveToBuf(_X, _Y)
// Check the length of the buffer, either 64 or 92 bytes
k.PublicKey = toBase64(buf)
var intlen int
switch k.Algorithm {
case ECDSAP256SHA256:
intlen = 32
case ECDSAP384SHA384:
intlen = 48
}
k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen))
return true
}
@ -618,9 +626,9 @@ func exponentToBuf(_E int) []byte {
// Set the public key for X and Y for Curve. The two
// values are just concatenated.
func curveToBuf(_X, _Y *big.Int) []byte {
buf := _X.Bytes()
buf = append(buf, _Y.Bytes()...)
func curveToBuf(_X, _Y *big.Int, intlen int) []byte {
buf := intToBytes(_X, intlen)
buf = append(buf, intToBytes(_Y, intlen)...)
return buf
}

View File

@ -126,7 +126,14 @@ func (r *DNSKEY) PrivateKeyString(p PrivateKey) (s string) {
"Coefficient: " + coefficient + "\n"
case *ecdsa.PrivateKey:
algorithm := strconv.Itoa(int(r.Algorithm)) + " (" + AlgorithmToString[r.Algorithm] + ")"
private := toBase64(t.D.Bytes())
var intlen int
switch r.Algorithm {
case ECDSAP256SHA256:
intlen = 32
case ECDSAP384SHA384:
intlen = 48
}
private := toBase64(intToBytes(t.D, intlen))
s = _FORMAT +
"Algorithm: " + algorithm + "\n" +
"PrivateKey: " + private + "\n"

11
msg.go
View File

@ -12,6 +12,7 @@ import (
"encoding/base32"
"encoding/base64"
"encoding/hex"
"math/big"
"math/rand"
"net"
"reflect"
@ -1305,6 +1306,16 @@ func UnpackStruct(any interface{}, msg []byte, off int) (int, error) {
}
// Helper function for packing and unpacking
func intToBytes(i *big.Int, length int) []byte {
buf := i.Bytes()
if len(buf) < length {
b := make([]byte, length)
copy(b[length-len(buf):], buf)
return b
}
return buf
}
func unpackUint16(msg []byte, off int) (uint16, int) {
return uint16(msg[off])<<8 | uint16(msg[off+1]), off + 2
}