# How fabrica-util Handles Certificate Management for Secure Microservice Communication

> Discover how fabrica-util security simplifies certificate management for microservices. Learn about ed25519 keys, X.509 generation, and mutual TLS authentication.

- Repository: [Pantheon/fabrica-util](https://github.com/go-pantheon/fabrica-util)
- Tags: how-to-guide
- Published: 2026-03-02

---

**The fabrica-util security package provides a lightweight, zero-dependency certificate lifecycle using ed25519 keys, supporting self-signed X.509 generation, PEM import/export, and cryptographic signing for mutual TLS and service-to-service authentication.**

fabrica-util is a Go utility library developed by go-pantheon that delivers a complete certificate management solution within its `security/certificate` package. The implementation relies exclusively on Go's standard library to generate ed25519 key pairs, create self-signed X.509 certificates, and handle PEM-encoded transport—making it ideal for containerized microservices requiring fast startup times and minimal attack surfaces.

## Certificate Lifecycle Overview

The `security/certificate` package in [`security/certificate/ed25519.go`](https://github.com/go-pantheon/fabrica-util/blob/main/security/certificate/ed25519.go) orchestrates a six-step workflow that covers the full spectrum of certificate operations needed for secure microservice communication:

- **Key Generation**: The `GenKeyPair` function (lines 38-48) invokes `ed25519.GenerateKey` to produce cryptographically secure private and public keys.
- **Certificate Creation**: `CreateSelfSignedCert` (lines 51-94) constructs an `x509.Certificate` template with configurable subject fields and validity periods, then signs it with the generated key pair.
- **PEM Export**: Utilities like `ExportPriToPEM` (lines 55-67) and `ExportPubToPEM` (lines 70-82) encode keys into PKCS#8 and PKIX PEM blocks for transport.
- **PEM Import**: `ImportPriFromPEM` (lines 95-113), `ImportPubFromPEM` (lines 115-131), and `ImportCertFromPEM` (lines 235-247) parse PEM data back into native Go types.
- **Validity Verification**: `VerifyCert` (lines 140-152) checks the current time against the certificate's `NotBefore` and `NotAfter` fields.
- **Cryptographic Signing**: `SignMessage` and `VerifyMessage` (or `Sign` and `Verify`) enable application-level proof-of-possession by signing arbitrary payloads with the private key.

## Generating Self-Signed Certificates with Ed25519

Microservices bootstrap their identity using ed25519-based self-signed certificates. The `CreateSelfSignedCert` function accepts a `pkix.Name` for subject configuration and a validity duration in days.

```go
package main

import (
	"crypto/x509/pkix"
	"log"

	"github.com/go-pantheon/fabrica-util/security/certificate"
)

func main() {
	// Create a self-signed cert valid for 365 days
	cert, err := certificate.CreateSelfSignedCert(pkix.Name{
		CommonName:   "service.my-domain.local",
		Organization: []string{"MyOrg"},
		Country:      []string{"US"},
	}, 365)
	if err != nil {
		log.Fatalf("cert creation failed: %v", err)
	}

	// Access the PEM-encoded certificate
	_ = cert.CertPEM
}

```

This process leverages `GenKeyPair` internally to generate the ed25519 key pair before constructing the X.509 structure. The resulting certificate includes proper key usage extensions for digital signatures and key encipherment.

## Importing and Exporting PEM Data

For inter-service communication, certificates and keys must serialize to PEM format for transport across network boundaries or storage in configuration systems.

### Exporting Keys for Transport

The package provides distinct export functions for private and public keys. `ExportPriToPEM` encodes the ed25519 private key into a PKCS#8 PEM block, while `ExportPubToPEM` handles PKIX format for public keys:

```go
// Export PEM for transport or TLS configuration
privPEM, err := certificate.ExportPriToPEM(cert.KeyPair.Pri)
if err != nil {
    log.Fatal(err)
}
pubPEM, err := certificate.ExportPubToPEM(cert.KeyPair.Pub)
if err != nil {
    log.Fatal(err)
}

```

### Parsing PEM Back to Native Types

On the receiving side, microservices parse PEM blobs back into usable cryptographic primitives:

```go
pri, err := certificate.ImportPriFromPEM(priPEM)
if err != nil {
    log.Fatalf("import private key: %v", err)
}
pub, err := certificate.ImportPubFromPEM(pubPEM)
if err != nil {
    log.Fatalf("import public key: %v", err)
}
cert, err := certificate.ImportCertFromPEM(certPEM)
if err != nil {
    log.Fatalf("import certificate: %v", err)
}

```

## Validating Certificates and Signatures

Before establishing trust, services must verify both temporal validity and cryptographic ownership.

### Time-Based Validity Checks

The `VerifyCert` function validates that the current time falls within the certificate's validity window:

```go
if err := certificate.VerifyCert(cert); err != nil {
    log.Fatalf("certificate not valid: %v", err)
}

```

### Message Signing for Proof of Possession

To prove ownership of the private key associated with a certificate, services can sign challenge messages. The `Sign` function produces Ed25519 signatures, while `Verify` validates them against the public key:

```go
msg := []byte("authentication-challenge")
sig, err := certificate.Sign(pri, msg)
if err != nil {
    log.Fatalf("signing failed: %v", err)
}
ok := certificate.Verify(pub, msg, sig.Sign)
log.Printf("signature valid: %t", ok)

```

This mechanism supports JWT-style authentication flows where services demonstrate possession of their certificate-bound keys without transmitting the private key material.

## Enabling Mutual TLS in Microservices

The PEM-encoded certificates integrate directly with Go's standard `tls` package for mutual TLS (mTLS) implementations. Microservices load their identity into `tls.Config` and configure client certificate requirements:

```go
tlsConfig := &tls.Config{
    Certificates: []tls.Certificate{
        {
            Certificate: [][]byte{certPEM},
            PrivateKey:  pri,
        },
    },
    ClientAuth: tls.RequireAndVerifyClientCert,
    RootCAs:    x509.NewCertPool(),
}
tlsConfig.RootCAs.AppendCertsFromPEM(trustedCertPEM)

```

The `Certificates` field accepts the PEM-encoded certificate and corresponding private key imported via the fabrica-util package. Setting `ClientAuth` to `tls.RequireAndVerifyClientCert` mandates that connecting services present valid certificates, creating a zero-trust communication mesh.

## Summary

- **fabrica-util** provides a complete certificate lifecycle in [`security/certificate/ed25519.go`](https://github.com/go-pantheon/fabrica-util/blob/main/security/certificate/ed25519.go) using only Go standard library components.
- The package generates **ed25519** key pairs and self-signed **X.509** certificates via `CreateSelfSignedCert` and `GenKeyPair`.
- **PEM import/export** functions enable secure transport of cryptographic material between services without external dependencies.
- **Validity checking** and **message signing** utilities support both TLS-level and application-level security verification.
- The lightweight implementation suits containerized microservices requiring fast startup and minimal resource overhead.

## Frequently Asked Questions

### What cryptographic algorithm does fabrica-util use for certificate keys?

The package exclusively uses **ed25519** (Edwards-curve Digital Signature Algorithm) for all key generation and signing operations. This modern elliptic-curve algorithm provides strong security with compact key sizes and fast performance, implemented through Go's standard `crypto/ed25519` package.

### Can fabrica-util certificates be used for mutual TLS (mTLS)?

Yes. The `security/certificate` package generates standard X.509 certificates that integrate directly with Go's `tls.Config`. Services can load the PEM-encoded certificates and private keys into the `Certificates` field and configure `ClientAuth: tls.RequireAndVerifyClientCert` to enforce mutual authentication between microservices.

### Does the security package require external dependencies?

No. The implementation relies solely on Go's standard library, including `crypto/ed25519`, `crypto/x509`, `crypto/x509/pkix`, and `encoding/pem`. This zero-dependency design minimizes the attack surface and eliminates version conflicts in containerized deployments.

### How does fabrica-util handle certificate expiration checking?

The `VerifyCert` function (lines 140-152 in [`ed25519.go`](https://github.com/go-pantheon/fabrica-util/blob/main/ed25519.go)) automatically checks the current system time against the certificate's `NotBefore` and `NotAfter` fields. This validation ensures that services reject expired or prematurely used certificates before establishing cryptographic trust.