# Certificates

Certificate management for BACEN mTLS authentication, XMLDSig message signing, and HTTPS TLS termination.

## Prerequisites

- Understanding of X.509 certificate formats (PEM, PKCS#12)
- Access to ICP-Brasil certificate authority (for BACEN integration)
- Certificate management tools (OpenSSL)

## Certificate Types

| Certificate | Purpose | Format | Environment Variable |
|-------------|---------|--------|---------------------|
| CPIC | mTLS client authentication with BACEN | PEM | `BACEN_CLIENT_CERT_PATH` |
| CPIC Private Key | mTLS private key | PEM | `BACEN_CLIENT_KEY_PATH` |
| CPIA | XMLDSig message signing (RSA-SHA256) | PEM | Loaded by CertificatePool |
| BACEN Root CA | BACEN server certificate validation | PEM | `BACEN_CA_CERT_PATH` |
| TLS Certificate | HTTPS termination | PEM | Ingress/LB configuration |

## ICP-Brasil Certificates

### Obtaining Certificates

1. Register with an ICP-Brasil accredited certificate authority (AC)
2. Request CPIC (authentication) and CPIA (signing) certificates
3. Complete the BCB enrollment process for SPI/DICT access

### Format Conversion

Monetarie PIX requires PEM format. Convert from PKCS#12:

```bash
# Extract client certificate
openssl pkcs12 -in institution.p12 -clcerts -nokeys -out cpic.pem

# Extract private key
openssl pkcs12 -in institution.p12 -nocerts -out cpic-key.pem

# Extract CA chain
openssl pkcs12 -in institution.p12 -cacerts -nokeys -out ca-chain.pem

# Verify certificate
openssl x509 -in cpic.pem -text -noout
```

### Certificate Validation

```bash
# Verify certificate chain
openssl verify -CAfile bacen-ca.pem cpic.pem

# Check certificate expiration
openssl x509 -in cpic.pem -enddate -noout

# Test mTLS connection to BACEN (homolog)
openssl s_client -connect dict-h.pi.rsfn.net.br:16522 \
  -cert cpic.pem -key cpic-key.pem -CAfile bacen-ca.pem
```

## Certificate Pool

`Shared.Crypto.CertificatePool` is a GenServer that manages certificates in memory with automatic refresh:

- Loads certificates on startup
- Refreshes every 5 minutes
- Provides signing keys to `XmlSigner` and `JwsSigner`

## XMLDSig Signing Specification

### SPI Messages

- 3 XML References: KeyInfo (by ID), AppHdr (empty URI), Document (no URI)
- Signature placed in `<Sgntr>` element within `<AppHdr>`
- Canonicalization: Exclusive XML C14N (`xml-exc-c14n#`)
- Signature Algorithm: RSA-SHA256
- Digest Algorithm: SHA-256

### DICT Messages

- 2 XML References: AppHdr + Document
- Same algorithms as SPI

## Kubernetes Secret Mounting

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: bacen-certs
  namespace: pix
type: Opaque
data:
  cpic.pem: <base64-encoded-cert>
  cpic-key.pem: <base64-encoded-key>
  bacen-ca.pem: <base64-encoded-ca>
---
# In backend deployment
spec:
  containers:
    - name: pix-backend
      volumeMounts:
        - name: bacen-certs
          mountPath: /certs
          readOnly: true
      env:
        - name: BACEN_CA_CERT_PATH
          value: /certs/bacen-ca.pem
        - name: BACEN_CLIENT_CERT_PATH
          value: /certs/cpic.pem
        - name: BACEN_CLIENT_KEY_PATH
          value: /certs/cpic-key.pem
  volumes:
    - name: bacen-certs
      secret:
        secretName: bacen-certs
```

## TLS Certificates (HTTPS)

### Kubernetes (cert-manager)

```yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: pix-tls
  namespace: pix
spec:
  secretName: monetarie-dev-tls
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - pixapi-dev.fluxiq.com.br
    - pixadmin-dev.fluxiq.com.br
```

### Self-Signed (Development)

```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=localhost"
```

## Certificate Rotation

### BACEN Certificates

1. Obtain new certificate before current one expires
2. Mount new certificate alongside existing one
3. Update environment variables to point to new certificate
4. Restart backend pods (rolling update)
5. Verify mTLS connectivity
6. Remove old certificate

### TLS Certificates

With cert-manager, rotation is automatic. For manual management:

1. Obtain new certificate
2. Update K8s Secret or HAProxy configuration
3. Reload (no downtime for most load balancers)

## Expected Outcome

After configuring certificates:

- BACEN mTLS connection established (if `BACEN_ENABLED=true`)
- XMLDSig signing operational for SPI and DICT messages
- HTTPS endpoints accessible with valid TLS
- Certificate refresh running in CertificatePool GenServer
