Documentation
¶
Overview ¶
Package certificate implements the certificate common-structure of I2P.
Package certificate implements the certificate common-structure of I2P.
Package certificate implements the certificate common-structure of I2P.
Package certificate implements the certificate common-structure of I2P.
Package certificate implements the I2P Certificate common data structure according to specification version 0.9.67.
Certificates are used throughout I2P to provide cryptographic metadata about keys, signatures, and other security parameters. They support multiple certificate types and provide flexible payload storage.
Overview ¶
The Certificate structure consists of:
- Type: Certificate type identifier (NULL, HASHCASH, HIDDEN, SIGNED, MULTIPLE, KEY)
- Length: Payload length in bytes (0-65535)
- Payload: Variable-length data specific to the certificate type
Certificate Types ¶
The package supports six certificate types:
- CERT_NULL (0): No certificate (legacy)
- CERT_HASHCASH (1): HashCash proof-of-work
- CERT_HIDDEN (2): Hidden router certificate (routers may not announce hidden status)
- CERT_SIGNED (3): Signed certificate
- CERT_MULTIPLE (4): Multiple certificates
- CERT_KEY (5): Key certificate with signing/crypto type info
Safe Constructors ¶
The package provides validated construction through the builder pattern:
// Create a KEY certificate with validation
builder := certificate.NewCertificateBuilder()
builder, err := builder.WithKeyTypes(7, 4) // Ed25519/X25519
if err != nil {
return err
}
cert, err := builder.Build()
if err != nil {
return err
}
// Create a NULL certificate (the default type; no further configuration needed)
cert, err := certificate.NewCertificateBuilder().Build()
Parsing from Bytes ¶
Certificates can be safely parsed from byte streams:
cert, remainder, err := certificate.ReadCertificate(data)
if err != nil {
return err
}
if !cert.IsValid() {
return errors.New("invalid certificate")
}
Validation ¶
All certificates support validation to ensure proper initialization:
// Boolean validation check
if !cert.IsValid() {
return errors.New("invalid certificate")
}
// Builder-level validation (before Build)
if err := builder.Validate(); err != nil {
// Fix configuration before building
}
Accessing Certificate Data ¶
Certificate fields can be safely accessed with error handling:
certType, err := cert.Type()
if err != nil {
return err
}
length, err := cert.Length()
if err != nil {
return err
}
payload, err := cert.Data()
if err != nil {
return err
}
Builder Pattern ¶
The CertificateBuilder provides fluent API with early validation:
// Builder validates configuration at each step
builder := NewCertificateBuilder()
builder, err := builder.WithType(CERT_KEY)
if err != nil {
return err // Invalid type rejected immediately
}
// Validate before building
if err := builder.Validate(); err != nil {
// Fix configuration issues
}
cert, err := builder.Build()
Best Practices ¶
- Use the builder pattern for creating new certificates
- Always validate certificates after parsing from bytes
- Use safe accessor methods (Type(), Length(), Data()) with error checking
- Prefer KEY certificates for modern cryptographic parameters
Specification ¶
Reference: https://geti2p.net/spec/common-structures#certificate
This implementation follows I2P specification version 0.9.67 and provides comprehensive validation and error handling for all certificate operations.
Index ¶
- Constants
- func BuildKeyTypePayload(signingType, cryptoType int) ([]byte, error)
- func GetCryptoTypeFromCertificate(cert Certificate) (int, error)
- func GetExcessCryptoPublicKeyData(cert Certificate, cryptoKeySize, excessSigningLen int) ([]byte, error)
- func GetExcessSigningPublicKeyData(cert Certificate, signingKeySize int) ([]byte, error)
- func GetSignatureTypeFromCertificate(cert Certificate) (int, error)
- type Certificate
- func (c *Certificate) Bytes() []byte
- func (c *Certificate) Data() ([]byte, error)
- func (c *Certificate) Equals(other *Certificate) bool
- func (c *Certificate) GoString() string
- func (c *Certificate) IsValid() bool
- func (c *Certificate) Length() (length int, err error)
- func (c *Certificate) RawBytes() []byte
- func (c *Certificate) String() string
- func (c *Certificate) Type() (certType int, err error)
- func (c *Certificate) Validate() error
- type CertificateBuilder
- func (cb *CertificateBuilder) Build() (*Certificate, error)
- func (cb *CertificateBuilder) Validate() error
- func (cb *CertificateBuilder) WithKeyTypes(signingType, cryptoType int) (*CertificateBuilder, error)
- func (cb *CertificateBuilder) WithPayload(payload []byte) (*CertificateBuilder, error)
- func (cb *CertificateBuilder) WithType(certType uint8) (*CertificateBuilder, error)
Constants ¶
const ( CERT_NULL = iota //nolint:golint CERT_HASHCASH //nolint:golint CERT_HIDDEN //nolint:golint CERT_SIGNED //nolint:golint CERT_MULTIPLE //nolint:golint CERT_KEY //nolint:golint )
Certificate Types
const CERT_CPK_SLOT_SIZE = 256
CERT_CPK_SLOT_SIZE is the number of bytes in the keys_and_cert structure reserved for the crypto public key. Crypto keys larger than this store the overflow bytes as excess crypto public key data in the KEY certificate payload after any excess signing key bytes.
const CERT_CRYPTO_KEY_TYPE_SIZE = 2
CERT_CRYPTO_KEY_TYPE_SIZE is the size in bytes of the crypto key type field in key certificates
const CERT_DEFAULT_TYPE_SIZE = 1
CERT_DEFAULT_TYPE_SIZE is the size in bytes for the certificate type field
const CERT_EMPTY_PAYLOAD_SIZE = 0
CERT_EMPTY_PAYLOAD_SIZE represents the size of an empty payload
const CERT_KEY_CRYPTO_TYPE_OFFSET = 2
CERT_KEY_CRYPTO_TYPE_OFFSET is the byte offset where crypto key type begins in KEY certificate payload
const CERT_KEY_SIG_TYPE_OFFSET = 0
CERT_KEY_SIG_TYPE_OFFSET is the byte offset where signature type begins in KEY certificate payload
const CERT_LENGTH_FIELD_END = 3
CERT_LENGTH_FIELD_END is the end index for the certificate length field (2 bytes total)
const CERT_LENGTH_FIELD_SIZE = 2
CERT_LENGTH_FIELD_SIZE is the size in bytes for the certificate length field
const CERT_LENGTH_FIELD_START = 1
CERT_LENGTH_FIELD_START is the start index for the certificate length field
const CERT_MAX_PAYLOAD_SIZE = 65535
CERT_MAX_PAYLOAD_SIZE is the maximum allowed size for certificate payload according to I2P specification (2 bytes can represent up to 65535)
const CERT_MAX_TYPE_VALUE = 255
CERT_MAX_TYPE_VALUE is the maximum valid certificate type value that fits in a single byte (0-255 range)
const CERT_MIN_KEY_PAYLOAD_SIZE = 4
CERT_MIN_KEY_PAYLOAD_SIZE is the minimum payload size required for KEY certificates to contain the signature type field (2 bytes minimum)
const CERT_MIN_SIZE = 3
CERT_MIN_SIZE is the minimum size of a valid Certificate in []byte 1 byte for type 2 bytes for payload length
const CERT_SIGNED_PAYLOAD_LONG = 72
CERT_SIGNED_PAYLOAD_LONG is the spec-defined SIGNED certificate payload length containing a 40-byte DSA signature followed by a 32-byte Hash of the signing Destination.
const CERT_SIGNED_PAYLOAD_SHORT = 40
CERT_SIGNED_PAYLOAD_SHORT is the spec-defined SIGNED certificate payload length containing a 40-byte DSA signature only.
const CERT_SIGNING_KEY_TYPE_SIZE = 2 //nolint:golint
CERT_SIGNING_KEY_TYPE_SIZE is the size in bytes of the signing key type field in key certificates
const CERT_SPK_SLOT_SIZE = 128
CERT_SPK_SLOT_SIZE is the number of bytes in the keys_and_cert structure reserved for the signing public key. Signing keys larger than this store the overflow bytes as excess signing public key data in the KEY certificate payload after the 4-byte type header.
const CERT_TYPE_FIELD_END = 1
CERT_TYPE_FIELD_END is the end index for the certificate type field (1 byte)
Variables ¶
This section is empty.
Functions ¶
func BuildKeyTypePayload ¶ added in v0.0.6
BuildKeyTypePayload is a convenience function to build key type payload without using builder. This is useful when you just need to generate the payload bytes.
Parameters:
- signingType: The signing key type (must be non-negative and <= 65535)
- cryptoType: The crypto key type (must be non-negative and <= 65535)
Returns:
- []byte: The 4-byte payload [signing_type][crypto_type]
- error: Non-nil if either type is negative or exceeds uint16 range
func GetCryptoTypeFromCertificate ¶ added in v0.1.5
func GetCryptoTypeFromCertificate(cert Certificate) (int, error)
GetCryptoTypeFromCertificate extracts the crypto public key type from a KEY certificate. Returns -1 (not 0) on every error path to avoid ambiguity with the valid ElGamal crypto type code 0. Callers must always check the returned error before using the int.
func GetExcessCryptoPublicKeyData ¶ added in v0.1.5
func GetExcessCryptoPublicKeyData(cert Certificate, cryptoKeySize, excessSigningLen int) ([]byte, error)
GetExcessCryptoPublicKeyData extracts the excess crypto public key bytes from a KEY certificate. For crypto key types whose total length exceeds CERT_CPK_SLOT_SIZE (256) bytes, the overflow is stored after any excess signing key data in the payload. The excessSigningLen parameter is the number of excess signing key bytes already stored before the crypto excess (= max(0, signingKeySize - CERT_SPK_SLOT_SIZE)). Returns nil (no error) when cryptoKeySize <= CERT_CPK_SLOT_SIZE.
func GetExcessSigningPublicKeyData ¶ added in v0.1.5
func GetExcessSigningPublicKeyData(cert Certificate, signingKeySize int) ([]byte, error)
GetExcessSigningPublicKeyData extracts the excess signing public key bytes from a KEY certificate. For signing key types whose total length exceeds CERT_SPK_SLOT_SIZE (128) bytes, the overflow is stored starting at byte CERT_MIN_KEY_PAYLOAD_SIZE of the payload. Returns nil (no error) when signingKeySize <= CERT_SPK_SLOT_SIZE.
func GetSignatureTypeFromCertificate ¶
func GetSignatureTypeFromCertificate(cert Certificate) (int, error)
GetSignatureTypeFromCertificate extracts the signature type from a KEY certificate. Returns an error if the certificate is not a KEY type or if the payload is too short.
Types ¶
type Certificate ¶
type Certificate struct {
// contains filtered or unexported fields
}
Certificate is the representation of an I2P Certificate.
https://geti2p.net/spec/common-structures#certificate
func NewCertificate ¶
func NewCertificate() *Certificate
NewCertificate creates a new Certificate with default NULL type. The returned certificate serializes to exactly CERT_MIN_SIZE (3) bytes: 1 byte type (0x00 = NULL) + 2 byte length (0x0000) + 0 byte payload.
func NewCertificateWithType ¶
func NewCertificateWithType(certType uint8, payload []byte) (*Certificate, error)
NewCertificateWithType creates a new Certificate with specified type and payload
func ReadCertificate ¶
func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error)
ReadCertificate creates a Certificate from []byte and returns any remaining bytes after the certificate. Returns nil certificate on error (not partial certificate). Per the I2P spec, type-specific payload length constraints are enforced as hard errors.
func (*Certificate) Bytes ¶
func (c *Certificate) Bytes() []byte
Bytes returns the entire certificate in []byte form, trims payload to specified length. Returns nil if the certificate is nil or not initialized.
func (*Certificate) Data ¶
func (c *Certificate) Data() ([]byte, error)
Data returns a copy of the payload of a Certificate, trimmed to the declared length. The returned slice is a defensive copy — callers may mutate it without affecting the certificate's internal state. Returns error if length is invalid.
func (*Certificate) Equals ¶ added in v0.1.5
func (c *Certificate) Equals(other *Certificate) bool
Equals returns true if the two certificates are identical in type, length, and payload. Two nil or uninitialized certificates are considered equal. A nil certificate and a valid certificate are never equal.
func (*Certificate) GoString ¶ added in v0.1.5
func (c *Certificate) GoString() string
GoString returns a Go-syntax representation of the Certificate for debugging. Implements the fmt.GoStringer interface.
func (*Certificate) IsValid ¶ added in v0.1.0
func (c *Certificate) IsValid() bool
IsValid returns true if the certificate is fully initialized and valid. This method checks that all required fields (kind, len) are present and non-empty. Note: payload can be empty for NULL certificates.
func (*Certificate) Length ¶
func (c *Certificate) Length() (length int, err error)
Length returns the payload length of a Certificate, with validation and error context.
func (*Certificate) RawBytes ¶
func (c *Certificate) RawBytes() []byte
RawBytes returns the entire certificate in []byte form, includes excess payload data. Returns nil if the certificate is nil or not initialized.
func (*Certificate) String ¶ added in v0.1.5
func (c *Certificate) String() string
String returns a human-readable representation of the Certificate. Returns "Certificate{invalid}" for nil or uninitialized certificates.
func (*Certificate) Type ¶
func (c *Certificate) Type() (certType int, err error)
Type returns the certificate type as int, with validation and error context. The type is specified in the first byte of the Certificate.
func (*Certificate) Validate ¶ added in v0.1.5
func (c *Certificate) Validate() error
Validate checks that the Certificate is properly initialized and has consistent internal structure. Returns an error describing the first issue found, or nil if valid.
type CertificateBuilder ¶ added in v0.0.6
type CertificateBuilder struct {
// contains filtered or unexported fields
}
CertificateBuilder provides a fluent interface for building certificates. This pattern simplifies certificate construction, especially for complex cases with custom payloads or key types.
Example usage:
cert, err := certificate.NewCertificateBuilder().
WithKeyTypes(7, 4). // Ed25519 signing, X25519 crypto
Build()
func NewCertificateBuilder ¶ added in v0.0.6
func NewCertificateBuilder() *CertificateBuilder
NewCertificateBuilder creates a new certificate builder with default NULL type.
func (*CertificateBuilder) Build ¶ added in v0.0.6
func (cb *CertificateBuilder) Build() (*Certificate, error)
Build creates the certificate with the configured options. Returns error if the configuration is invalid.
Example:
cert, err := NewCertificateBuilder().
WithKeyTypes(7, 4).
Build()
func (*CertificateBuilder) Validate ¶ added in v0.1.0
func (cb *CertificateBuilder) Validate() error
Validate checks the builder configuration for consistency. This allows catching configuration errors before calling Build().
Example:
builder := NewCertificateBuilder().WithType(CERT_KEY)
if err := builder.Validate(); err != nil {
// Fix configuration before building
}
func (*CertificateBuilder) WithKeyTypes ¶ added in v0.0.6
func (cb *CertificateBuilder) WithKeyTypes(signingType, cryptoType int) (*CertificateBuilder, error)
WithKeyTypes sets signing and crypto key types (for CERT_KEY type). This is a convenience method that automatically:
- Sets the certificate type to CERT_KEY
- Builds the appropriate 4-byte payload
Parameters:
- signingType: The signing key type (e.g., 7 for Ed25519)
- cryptoType: The crypto key type (e.g., 4 for X25519)
Returns error if the key types are invalid (negative values or exceed uint16 range). On error, the builder retains its previous state and remains usable. Callers must check the returned error; ignoring it will silently proceed with the previously-set key types.
Example:
builder.WithKeyTypes(7, 4) // Ed25519 signing, X25519 crypto
func (*CertificateBuilder) WithPayload ¶ added in v0.0.6
func (cb *CertificateBuilder) WithPayload(payload []byte) (*CertificateBuilder, error)
WithPayload sets custom payload data. This overrides any payload that would be generated from key types. Returns error if the payload exceeds the maximum allowed size. On error, the builder retains its previous state and remains usable. Callers must check the returned error; ignoring it will silently proceed with the previously-set payload.
Example:
builder, err = builder.WithPayload(signatureData)
func (*CertificateBuilder) WithType ¶ added in v0.0.6
func (cb *CertificateBuilder) WithType(certType uint8) (*CertificateBuilder, error)
WithType sets the certificate type. Valid types are: CERT_NULL, CERT_HASHCASH, CERT_HIDDEN, CERT_SIGNED, CERT_MULTIPLE, CERT_KEY. Returns error if the certificate type is invalid.
On error, the builder retains its previous state and remains usable. Callers must check the returned error; ignoring it will silently proceed with the previously-set certificate type.
Example:
builder.WithType(certificate.CERT_KEY)