Fix key_certificate parsing/construction from data

This commit is contained in:
idk
2021-10-25 21:02:45 -04:00
parent bffc1dfe38
commit a87847ef51
5 changed files with 83 additions and 43 deletions

View File

@ -28,4 +28,4 @@ fmt:
find . -name '*.go' -exec gofmt -w -s {} \; find . -name '*.go' -exec gofmt -w -s {} \;
testcommon: testcommon:
$(GO) test -v -failfast ./lib/common/... $(GO) test -failfast ./lib/common/...

View File

@ -70,14 +70,18 @@ func (certificate Certificate) SignatureSize() (size int) {
func (certificate Certificate) Cert() []byte { func (certificate Certificate) Cert() []byte {
var ret []byte var ret []byte
ret = append(ret, certificate.CertType.Bytes()...) ret = append(ret, certificate.CertType.Bytes()...)
l, _ := certificate.Length()
//if err != nil && err.Error() != "certificate parsing warning: certificate data is shorter than specified by length" {
//}
data, _ := certificate.Data() data, _ := certificate.Data()
if certificate.CertLen.Value() != 0 && len(data) != 0 { if l != 0 && len(data) != 0 {
ret = append(ret, certificate.CertLen.Bytes()...) ret = append(ret, certificate.CertLen.Bytes()...)
ret = append(ret, data...) ret = append(ret, data...)
} else { } else {
ret = append(ret, certificate.CertLen.Bytes()...) ret = append(ret, certificate.CertLen.Bytes()...)
} }
return ret //log.Println("\n\n CERTIFICATE: ", ret, l+CERT_MIN_SIZE, err)
return ret //[:l+CERT_MIN_SIZE]
} }
// //
@ -111,7 +115,7 @@ func (certificate Certificate) Length() (length int, err error) {
"reason": "certificate data is shorter than specified by length", "reason": "certificate data is shorter than specified by length",
}).Warn("certificate format warning") }).Warn("certificate format warning")
err = errors.New("certificate parsing warning: certificate data is shorter than specified by length") err = errors.New("certificate parsing warning: certificate data is shorter than specified by length")
length = len(certificate.CertBytes) length = certificate.CertLen.Value()
} }
if certificate.CertLen.Value() < len(certificate.CertBytes) { if certificate.CertLen.Value() < len(certificate.CertBytes) {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -120,14 +124,13 @@ func (certificate Certificate) Length() (length int, err error) {
"certificate_actual_length": len(certificate.CertBytes), "certificate_actual_length": len(certificate.CertBytes),
"reason": "certificate contains data beyond length", "reason": "certificate contains data beyond length",
}).Warn("certificate format warning") }).Warn("certificate format warning")
err = errors.New("certificate parsing warning: certificate contains data beyond length") err = errors.New("certificate parsing warning: certificate data is longer than specified by length")
length = certificate.CertLen.Value() length = certificate.CertLen.Value()
return
} }
length = certificate.CertLen.Value()
if err != nil { if err != nil {
return return
} }
length = certificate.CertLen.Value()
return return
} }
@ -144,7 +147,7 @@ func (certificate Certificate) Data() (data []byte, err error) {
case "certificate parsing warning: certificate data is shorter than specified by length": case "certificate parsing warning: certificate data is shorter than specified by length":
data = certificate.CertBytes data = certificate.CertBytes
return return
case "certificate parsing warning: certificate contains data beyond length": case "certificate parsing warning: certificate data is longer than specified by length":
data = certificate.CertBytes[:certificate.CertLen.Value()] data = certificate.CertBytes[:certificate.CertLen.Value()]
return return
} }
@ -159,6 +162,16 @@ func (certificate Certificate) Data() (data []byte, err error) {
func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) { func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) {
certificate = &Certificate{} certificate = &Certificate{}
certificate.CertType, err = NewInteger(data[0:1]) certificate.CertType, err = NewInteger(data[0:1])
if err != nil {
log.WithFields(log.Fields{
"at": "(Certificate) ReadCertificate",
"certificate": certificate,
"data": data,
"reason": "error parsing certificate type",
"error": err,
"error_reason": err.Error(),
}).Warn("certificate format warning")
}
certificate.CertLen = &Integer{} certificate.CertLen = &Integer{}
cert_len := len(data) cert_len := len(data)
@ -174,6 +187,7 @@ func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, e
} else { } else {
certificate.CertLen, err = NewInteger(data[1:CERT_MIN_SIZE]) certificate.CertLen, err = NewInteger(data[1:CERT_MIN_SIZE])
// _, err = certificate.Type() // _, err = certificate.Type()
//log.Println("Calculated len AT LEN", cert_len, "Stated len AT LEN", certificate.CertLen.Value())
if err != nil { if err != nil {
//return //return
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -182,7 +196,7 @@ func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, e
"certificate_min_size": CERT_MIN_SIZE, "certificate_min_size": CERT_MIN_SIZE,
"reason": "certificate size is invalid", "reason": "certificate size is invalid",
}).Warn("certificate format warning") }).Warn("certificate format warning")
err = errors.New("error parsing certificate type: certificate type is invalid") //err = errors.New("error parsing certificate type: certificate type is invalid")
} }
certificate.CertBytes = data[CERT_MIN_SIZE:] certificate.CertBytes = data[CERT_MIN_SIZE:]
_, err = certificate.Length() _, err = certificate.Length()
@ -192,12 +206,11 @@ func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, e
certificate.CertLen, err = NewInteger([]byte{00000000}) certificate.CertLen, err = NewInteger([]byte{00000000})
return return
case "certificate parsing warning: certificate data is shorter than specified by length": case "certificate parsing warning: certificate data is shorter than specified by length":
//err = nil
return return
case "certificate parsing warning: certificate contains data beyond length": case "certificate parsing warning: certificate data is longer than specified by length":
certificate.CertBytes = data[CERT_MIN_SIZE:] certificate.CertBytes = data[CERT_MIN_SIZE:]
remainder = data[CERT_MIN_SIZE+certificate.CertLen.Value():] l, _ := certificate.Length()
err = nil remainder = data[CERT_MIN_SIZE+l:]
return return
} }
} }

View File

@ -1,8 +1,9 @@
package common package common
import ( import (
"github.com/stretchr/testify/assert"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestCertificateTypeIsFirstByte(t *testing.T) { func TestCertificateTypeIsFirstByte(t *testing.T) {
@ -24,11 +25,13 @@ func TestCertificateLengthCorrect(t *testing.T) {
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff} bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff}
certificate, _, err := ReadCertificate(bytes) certificate, _, err := ReadCertificate(bytes)
assert.Nil(err, "ReadCertificate() should not return an error with valid data")
cert_len, err := certificate.Length() cert_len, err := certificate.Length()
assert.Nil(err) assert.Nil(err, "ReadCertificate() should not return an error with valid data")
assert.Equal(cert_len, 2, "certificate.Length() should return integer from second two bytes") assert.Equal(cert_len, 2, "certificate.Length() should return integer from second two bytes")
assert.Nil(err) assert.Nil(err, "ReadCertificate() should not return an error with valid data")
} }
func TestCertificateLengthErrWhenTooShort(t *testing.T) { func TestCertificateLengthErrWhenTooShort(t *testing.T) {
@ -52,7 +55,14 @@ func TestCertificateLengthErrWhenDataTooShort(t *testing.T) {
bytes := []byte{0x03, 0x00, 0x02, 0xff} bytes := []byte{0x03, 0x00, 0x02, 0xff}
certificate, _, err := ReadCertificate(bytes) certificate, _, err := ReadCertificate(bytes)
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error(), "correct error message should be returned")
}
cert_len, err := certificate.Length() cert_len, err := certificate.Length()
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error(), "correct error message should be returned")
}
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was actually missing") assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was actually missing")
if assert.NotNil(err) { if assert.NotNil(err) {
@ -80,11 +90,14 @@ func TestCertificateDataWhenTooLong(t *testing.T) {
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa} bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa}
certificate, _, err := ReadCertificate(bytes) certificate, _, err := ReadCertificate(bytes)
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is longer than specified by length", err.Error(), "correct error message should be returned")
}
cert_len, err := certificate.Length() cert_len, err := certificate.Length()
if assert.NotNil(err) { if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate contains data beyond length", err.Error(), "correct error message should be returned") assert.Equal("certificate parsing warning: certificate data is longer than specified by length", err.Error(), "correct error message should be returned")
} }
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was too long") assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was too long")
@ -98,6 +111,9 @@ func TestCertificateDataWhenTooShort(t *testing.T) {
bytes := []byte{0x03, 0x00, 0x02, 0xff} bytes := []byte{0x03, 0x00, 0x02, 0xff}
certificate, _, err := ReadCertificate(bytes) certificate, _, err := ReadCertificate(bytes)
if assert.NotNil(err) {
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error(), "correct error message should be returned")
}
cert_data, err := certificate.Data() cert_data, err := certificate.Data()
if assert.NotNil(err) { if assert.NotNil(err) {
@ -142,7 +158,7 @@ func TestReadCertificateWithRemainder(t *testing.T) {
assert.Equal(len(cert.Cert()), 5, "ReadCertificate() did not return correct amount of data for certificate with extra data") assert.Equal(len(cert.Cert()), 5, "ReadCertificate() did not return correct amount of data for certificate with extra data")
assert.Equal(len(remainder), 1, "ReadCertificate() returned incorrect length remainder on certificate with extra data") assert.Equal(len(remainder), 1, "ReadCertificate() returned incorrect length remainder on certificate with extra data")
assert.Equal(1, int(remainder[0]), "ReadCertificate() did not return correct remainder value") assert.Equal(1, int(remainder[0]), "ReadCertificate() did not return correct remainder value")
assert.Nil(err) assert.NotNil(err)
} }
func TestReadCertificateWithInvalidLength(t *testing.T) { func TestReadCertificateWithInvalidLength(t *testing.T) {

View File

@ -28,6 +28,7 @@ payload :: data
import ( import (
"errors" "errors"
"github.com/go-i2p/go-i2p/lib/crypto" "github.com/go-i2p/go-i2p/lib/crypto"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -78,6 +79,10 @@ const (
KEYCERT_SPK_SIZE = 128 KEYCERT_SPK_SIZE = 128
) )
const (
KEYCERT_MIN_SIZE = 7
)
type KeyCertificate struct { type KeyCertificate struct {
CertificateInterface CertificateInterface
PKType *Integer PKType *Integer
@ -106,15 +111,15 @@ func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_typ
// data_len := len(key_certificate.CertificateInterface.CertBytes) // data_len := len(key_certificate.CertificateInterface.CertBytes)
if len(key_certificate.SPKType.Bytes()) < 2 { if len(key_certificate.SPKType.Bytes()) < 2 {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(KeyCertificate) SingingPublicKeyType", "at": "(KeyCertificate) SigningPublicKeyType",
"data_len": len(key_certificate.SPKType.Bytes()), "data_len": len(key_certificate.SPKType.Bytes()),
"required_len": 2, "required_len": 2,
"reason": "not enough data", "reason": "not enough data",
}).Error("error retrieving Singning Public Key type") }).Error("error retrieving Signing Public Key type")
err = errors.New("error retrieving signing public key type: not enough data") err = errors.New("error retrieving signing public key type: not enough data")
return return
} }
log.Println("Signing Public Key Type", key_certificate.SPKType) log.Println("Signing Public Key Type", key_certificate.SPKType) //.Value())
return key_certificate.SPKType.Value(), nil return key_certificate.SPKType.Value(), nil
} }
@ -254,7 +259,7 @@ func (key_certificate KeyCertificate) SignatureSize() (size int) {
func ReadKeyCertificate(data []byte) (key_certificate KeyCertificate, err error) { func ReadKeyCertificate(data []byte) (key_certificate KeyCertificate, err error) {
key_certificate.SPKType = &Integer{} key_certificate.SPKType = &Integer{}
key_certificate.PKType = &Integer{} key_certificate.PKType = &Integer{}
cert, _, err := ReadCertificate(data) cert, remainder, err := ReadCertificate(data)
if err != nil { if err != nil {
return return
} }
@ -262,35 +267,37 @@ func ReadKeyCertificate(data []byte) (key_certificate KeyCertificate, err error)
if err != nil { if err != nil {
return return
} }
log.Println("KEYSANDCERT CERT TYPE=", cert_type, cert.CertBytes) log.Println("KEYSANDCERT CERT TYPE=", cert_type, cert.CertBytes, remainder)
key_certificate.CertificateInterface = cert key_certificate.CertificateInterface = cert
data = cert.CertBytes data = cert.Cert()
data_len := len(data) data_len := len(data)
if data_len < 2 { if data_len < KEYCERT_MIN_SIZE {
log.WithFields(log.Fields{
"at": "(KeyCertificate) SigningPublicKeyType",
"data_len": data_len,
"required_len": 2,
"reason": "not enough data",
}).Error("error parsing key certificate signing public key")
err = errors.New("error parsing key certificate signing public key: not enough data")
// key_certificate.SPKType, err = NewInteger(data[:])
key_certificate.PKType, err = NewInteger(data[:])
return
}
// key_certificate.SPKType, err = NewInteger(data[0:2])
key_certificate.PKType, err = NewInteger(data[0:2])
if data_len < 4 {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"at": "(KeyCertificate) PublicKeyType", "at": "(KeyCertificate) PublicKeyType",
"data_len": data_len, "data_len": data_len,
"required_len": 4, "required_len": KEYCERT_MIN_SIZE,
"reason": "not enough data", "reason": "not enough data",
}).Error("error parsing key certificate public key") }).Error("error parsing key certificate public key")
err = errors.New("error parsing key certificate public key: not enough data") err = errors.New("error parsing key certificate public key: not enough data")
return return
} }
// key_certificate.PKType, err = NewInteger(data[2:4]) log.Println("KEYSANDCERT=", data, "| len=", data_len, "| 0=", data[0], "| 1=", data[1])
key_certificate.SPKType, err = NewInteger(data[2:4]) key_certificate.SPKType, err = NewInteger(data[len(data)-2 : len(data)])
if err != nil {
log.WithFields(log.Fields{
"at": "(KeyCertificate) SigningPublicKeyType",
"key_type": key_certificate.PKType,
"reason": "failed to read signing public key type",
}).Error("error parsing key certificate signing public key")
}
key_certificate.PKType, err = NewInteger(data[len(data)-4 : len(data)-2])
if err != nil {
log.WithFields(log.Fields{
"at": "(KeyCertificate) PublicKeyType",
"key_type": key_certificate.PKType,
"reason": "failed to read public key type",
}).Error("error parsing key certificate public key")
err = errors.New("error parsing key certificate public key: not enough data")
}
return return
} }

View File

@ -1,8 +1,9 @@
package common package common
import ( import (
"github.com/stretchr/testify/assert"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestSingingPublicKeyTypeReturnsCorrectInteger(t *testing.T) { func TestSingingPublicKeyTypeReturnsCorrectInteger(t *testing.T) {
@ -20,6 +21,9 @@ func TestPublicKeyTypeReportsWhenDataTooSmall(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
key_cert, err := ReadKeyCertificate([]byte{0x05, 0x00, 0x01, 0x00}) key_cert, err := ReadKeyCertificate([]byte{0x05, 0x00, 0x01, 0x00})
if assert.NotNil(err) {
assert.Equal("error parsing key certificate public key: not enough data", err.Error(), "correct error message should be returned")
}
// assert.NotNil(err, "ReadKeyCertificate() returned error with valid data") // assert.NotNil(err, "ReadKeyCertificate() returned error with valid data")
_, err = key_cert.PublicKeyType() _, err = key_cert.PublicKeyType()