diff --git a/lib/common/certificate.go b/lib/common/certificate.go index e3aab7b..cecc84b 100644 --- a/lib/common/certificate.go +++ b/lib/common/certificate.go @@ -92,7 +92,7 @@ func (certificate Certificate) Length() (length int, err error) { "certificate_length_field": length, "expected_bytes_length": inferred_len, "reason": "data longer than expected", - }).Error("certificate format warning") + }).Warn("certificate format warning") err = errors.New("certificate parsing warning: certificate contains data beyond length") } return diff --git a/lib/common/key_certificate.go b/lib/common/key_certificate.go index 0050aa1..0efd4d1 100644 --- a/lib/common/key_certificate.go +++ b/lib/common/key_certificate.go @@ -4,6 +4,26 @@ package common I2P Key Certificate https://geti2p.net/en/docs/spec/common-structures#type_Certificate Accurate for version 0.9.24 + ++----+----+----+----+----+-// +|type| length | payload ++----+----+----+----+----+-// + +type :: Integer + length -> 1 byte + + case 0 -> NULL + case 1 -> HASHCASH + case 2 -> HIDDEN + case 3 -> SIGNED + case 4 -> MULTIPLE + case 5 -> KEY + +length :: Integer + length -> 2 bytes + +payload :: data + length -> $length bytes */ import ( @@ -124,7 +144,7 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke "required_len": KEYCERT_PUBKEY_SIZE, "reason": "not enough data", }).Error("error constructing public key") - err = errors.New("error constucting public key: not enough data") + err = errors.New("error constructing public key: not enough data") return } switch key_type { @@ -140,7 +160,7 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke // Given some bytes, build a SigningPublicKey using any excess data that may be stored in the KeyCertificate and return // it along with any errors encountered constructing the SigningPublicKey. // -func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey) { +func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error) { signing_key_type, err := key_certificate.PublicKeyType() if err != nil { return @@ -152,7 +172,7 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si "required_len": KEYCERT_SPK_SIZE, "reason": "not enough data", }).Error("error constructing signing public key") - err = errors.New("error constucting signing public key: not enough data") + err = errors.New("error constructing signing public key: not enough data") return } switch signing_key_type { diff --git a/lib/common/key_certificate_test.go b/lib/common/key_certificate_test.go index 805d0c7..cb051ee 100644 --- a/lib/common/key_certificate_test.go +++ b/lib/common/key_certificate_test.go @@ -1 +1,125 @@ package common + +import ( + "testing" +) + +func TestSingingPublicKeyTypeReturnsCorrectInteger(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00}) + pk_type, err := key_cert.SigningPublicKeyType() + if err != nil { + t.Fatal("err reading SigningPublicKey type on valid data:", err) + } + if pk_type != KEYCERT_SIGN_P521 { + t.Fatal("SigningPublicKeyType did not return correct type:", pk_type) + } +} + +func TestSingingPublicKeyTypeReportsWhenDataTooSmall(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x01, 0x00}) + _, err := key_cert.SigningPublicKeyType() + if err == nil || err.Error() != "error parsing key certificate: not enough data" { + t.Fatal("incorrect error reported by SigningPublicKeyType:", err) + } +} + +func TestPublicKeyTypeReturnsCorrectInteger(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03}) + pk_type, err := key_cert.PublicKeyType() + if err != nil { + t.Fatal("err reading PublicKey type on valid data:", err) + } + if pk_type != KEYCERT_SIGN_P521 { + t.Fatal("PublicKeyType did not return correct type:", pk_type) + } +} + +func TestPublicKeyTypeReportsWhenDataTooSmall(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x02, 0x00, 0x00}) + _, err := key_cert.PublicKeyType() + if err == nil || err.Error() != "error parsing key certificate: not enough data" { + t.Fatal("incorrect error reported by PublicKeyType:", err) + } +} + +func TestConstructPublicKeyReportsWhenDataTooSmall(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}) + data := make([]byte, 255) + _, err := key_cert.ConstructPublicKey(data) + if err == nil || err.Error() != "error constructing public key: not enough data" { + t.Fatal("ConstructPubliKey reported incorrect error with missing data:", err) + } +} + +func TestConstructPublicKeyReturnsCorrectDataWithElg(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}) + data := make([]byte, 256) + pk, err := key_cert.ConstructPublicKey(data) + if err != nil { + t.Fatal("ConstructPublicKey returned error with valid data:", err) + } + if pk.Len() != 256 { + t.Fatal("ConstructPublicKey did not return public key with correct length") + } +} + +func TestConstructSigningPublicKeyReportsWhenDataTooSmall(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}) + data := make([]byte, 127) + _, err := key_cert.ConstructSigningPublicKey(data) + if err == nil || err.Error() != "error constructing signing public key: not enough data" { + t.Fatal("ConstructSigngingPubliKey reported incorrect error with missing data:", err) + } +} + +func TestConstructSigningPublicKeyWithDSASHA1(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}) + data := make([]byte, 128) + spk, err := key_cert.ConstructSigningPublicKey(data) + if err != nil { + t.Fatal("ConstructSigningPublicKey with DSA SHA1 returned err on valid data:", err) + } + spk_len := spk.Len() + if spk_len != KEYCERT_SIGN_DSA_SHA1_SIZE { + t.Fatal("ConstructSigningPublicKeyWithDSASHA1 returned incorrect SigningPublicKey length:", spk_len) + } +} + +func TestConstructSigningPublicKeyWithP256(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01}) + data := make([]byte, 128) + spk, err := key_cert.ConstructSigningPublicKey(data) + if err != nil { + t.Fatal("ConstructSigningPublicKey with P256 returned err on valid data:", err) + } + spk_len := spk.Len() + if spk_len != KEYCERT_SIGN_P256_SIZE { + t.Fatal("ConstructSigningPublicKey with P256 returned incorrect SigningPublicKey length:", spk_len) + } +} + +func TestConstructSigningPublicKeyWithP384(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02}) + data := make([]byte, 128) + spk, err := key_cert.ConstructSigningPublicKey(data) + if err != nil { + t.Fatal("ConstructSigningPublicKey with P384 returned err on valid data:", err) + } + spk_len := spk.Len() + if spk_len != KEYCERT_SIGN_P384_SIZE { + t.Fatal("ConstructSigningPublicKey with P384 returned incorrect SigningPublicKey length:", spk_len) + } +} + +func TestConstructSigningPublicKeyWithP521(t *testing.T) { + key_cert := KeyCertificate([]byte{0x05, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}) + data := make([]byte, 128) + spk, err := key_cert.ConstructSigningPublicKey(data) + if err != nil { + t.Fatal("ConstructSigningPublicKey with P521 returned err on valid data:", err) + } + spk_len := spk.Len() + if spk_len != KEYCERT_SIGN_P521_SIZE { + t.Fatal("ConstructSigningPublicKey with P521 returned incorrect SigningPublicKey length:", spk_len) + } +} diff --git a/lib/common/keys_and_cert.go b/lib/common/keys_and_cert.go index eb9ca9a..02b9141 100644 --- a/lib/common/keys_and_cert.go +++ b/lib/common/keys_and_cert.go @@ -121,7 +121,7 @@ func (keys_and_cert KeysAndCert) SigningPublicKey() (signing_public_key crypto.S // This KeysAndCert contains a Key Certificate, construct // a SigningPublicKey from the data in the KeysAndCert and // any additional data in the Certificate. - signing_public_key = KeyCertificate(cert).ConstructSigningPublicKey( + signing_public_key, err = KeyCertificate(cert).ConstructSigningPublicKey( keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE], ) } else { diff --git a/lib/common/lease_set.go b/lib/common/lease_set.go index 0873b59..17c5f23 100644 --- a/lib/common/lease_set.go +++ b/lib/common/lease_set.go @@ -164,7 +164,7 @@ func (lease_set LeaseSet) SigningKey() (signing_public_key crypto.SigningPublicK // This LeaseSet's Destination's Certificate is a Key Certificate, // create the signing publickey key using any data that might be // contained in the key certificate. - signing_public_key = KeyCertificate(cert).ConstructSigningPublicKey( + signing_public_key, err = KeyCertificate(cert).ConstructSigningPublicKey( lease_set[offset : offset+LEASE_SET_SPK_SIZE], ) } else {