fisc

Certificate Management

FiscGuy uses mutual TLS authentication with ZIMRA FDMS. The device must hold a valid certificate issued by ZIMRA to submit any signed request.


How Certificates Work

  1. init_device generates an RSA key pair and a Certificate Signing Request (CSR)
  2. The CSR is sent to ZIMRA FDMS RegisterDevice endpoint
  3. ZIMRA returns a signed certificate
  4. The certificate and private key are stored in the Certs model
  5. Every request to FDMS uses the certificate for mutual TLS authentication

Certificate Storage

Certificates are stored in the Certs model:

from fiscguy.models import Certs

cert = Certs.objects.first()
print(cert.certificate)      # PEM-encoded certificate
print(cert.certificate_key)  # PEM-encoded private key
print(cert.csr)              # Original CSR
print(cert.production)       # True = production, False = testing

At runtime, ZIMRAClient writes the certificate and key to a temporary PEM file used by the requests session. The temp file is cleaned up when the client is closed.


Certificate Renewal

Certificates expire. When they do, all signed requests will fail with BadCertificateSignature or an authentication error.

Via REST endpoint

POST /fiscguy/issue-certificate/

Response on success:

{"message": "Certificate issued successfully"}

Via Python

from fiscguy.services.certs_service import CertificateService
from fiscguy.models import Device

device = Device.objects.first()
CertificateService(device).issue_certificate()

Raises

Exception Cause
CertificateError FDMS rejected the renewal request
Exception Unexpected error during renewal

Key Generation

FiscGuy supports two key algorithms as per ZIMRA spec section 12:

Algorithm Spec reference
RSA 2048 Section 12.1.2
ECC ECDSA secp256r1 (P-256) Section 12.1.1

The cryptography library is used for all key generation and signing. pyOpenSSL is no longer used.


Security Notes


Checking Certificate Status

from fiscguy import get_status

status = get_status()
# Check for certificate-related errors in the response
print(status)

If the certificate is expired or invalid, get_status() will raise StatusError with an authentication error from FDMS.