---
component: provenance-governor
version: "1.7"
slug: provenance-governor/app-config-signing-keys
canonical_url: "https://docs.gradle.com/develocity/provenance-governor/1.7/app-config-signing-keys/"
title: "Signing Keys Configuration"
description: "Configuration for DSSE signing keys."
keywords:
  - "attestation"
  - "authentication"
  - "configuration"
status: current
---

<!-- llms-index: https://docs.gradle.com/develocity/llms.txt -->

# Signing Keys Configuration

<a id="preamble"></a>

Develocity Provenance Governor signs all published attestations using [Dead Simple Signing Envelope (DSSE)](https://github.com/secure-systems-lab/dsse/blob/master/background.md) for cryptographic integrity and authenticity. Signing keys are a best practice for any production deployment.

> [!IMPORTANT]
> Signing keys are strongly recommended in production. Without signing keys: Attestations are unsigned, cannot be reliably trusted, and policy validation cannot verify provenance integrity. With signing keys: All attestations are DSSE-wrapped and cryptographically signed. To enable signature validation in policies, you must also create a TrustedPublicKeys policy with your public key(s) (see verification).

<a id="cheat-sheet-key-naming-property-conventions"></a>

## Cheat Sheet: Key Naming & Property Conventions

<table class="tableblock frame-all grid-all stretch"><colgroup><col style="width: 12.5%;"> <col style="width: 25%;"> <col style="width: 25%;"> <col style="width: 12.5%;"> <col style="width: 25%;"></colgroup><tbody><tr><td class="tableblock halign-left valign-top">Integration</td><td class="tableblock halign-left valign-top">Secret Key Pattern</td><td class="tableblock halign-left valign-top">ConfigMap Key Pattern</td><td class="tableblock halign-left valign-top">Required</td><td class="tableblock halign-left valign-top">Notes</td></tr><tr><td class="tableblock halign-left valign-top">Private Signing Key</td><td class="tableblock halign-left valign-top">signing.key.<key>.private-pem</key></td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">Base64 PEM (see below for adding)</td></tr><tr><td class="tableblock halign-left valign-top">Public Signing Key</td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top">signing.key.<key>.public-pem</key></td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">PEM block</td></tr><tr><td class="tableblock halign-left valign-top">application.yml key (alternate)</td><td class="tableblock halign-left valign-top">signing.keys[0].key</td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">PEM private under array</td></tr><tr><td class="tableblock halign-left valign-top">Artifactory Instance</td><td class="tableblock halign-left valign-top">artifactory.instances.<name>.access-token</name></td><td class="tableblock halign-left valign-top">artifactory.instances.<name>.uri</name></td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">For storing attestations</td></tr><tr><td class="tableblock halign-left valign-top">Basic Identity</td><td class="tableblock halign-left valign-top">basic.identities.<name></name></td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">bcrypt recommended</td></tr></tbody></table>

Use unique, timestamped or versioned KEY names for rotation: e.g. `org1-20250220` or `signing-key-v2`. Use the same key name for both private and public components.

<a id="generating-and-configuring-signing-keys"></a>

## Generating and Configuring Signing Keys

You may use any of these supported signing algorithms for attestation generation:

*   **Ed25519** (recommended): Small, fast, secure. Most deployments should use this.
    
*   **ECDSA prime256v1**: Standard elliptic curve, compatible with Artifactory.
    
*   **RSA 2048**: Larger signatures; legacy, use only if required.
    

<a id="step-1-generate-a-key-pair"></a>

### Step 1: Generate a Key Pair

**Ed25519 (Recommended):**

```
openssl genpkey -algorithm Ed25519 -out private-key.pem
openssl pkey -in private-key.pem -pubout -out public-key.pem
```

**ECDSA prime256v1:**

```
openssl ecparam -name prime256v1 -genkey -noout -out ec_private.key
openssl pkcs8 -topk8 -inform PEM -in ec_private.key -outform PEM -nocrypt -out private-key.pem
openssl ec -in ec_private.key -pubout -out public-key.pem
```

**RSA 2048:**

```
openssl genrsa -out private-key.pem 2048
openssl rsa -in private-key.pem -pubout -out public-key.pem
```

Use naming patterns (timestamps/versions) in all filenames and secret keys for clarity and rotation (e.g. `org1-20250315`, `signing-key-v2`).

<a id="step-2-add-keys-to-your-kubernetes-secrets"></a>

### Step 2: Add Keys to Your Kubernetes Secrets

You can add keys in three ways:

**Option A: application.yml (stringData):**

```
apiVersion: v1
kind: Secret
metadata:
  name: secrets
  namespace: develocity-provenance-governor
type: Opaque
stringData:
  application.yml: |
    signing:
      keys:
        - key: |
            -----BEGIN PRIVATE KEY-----
            ...
            -----END PRIVATE KEY-----
```

**Option B: Individual Properties (base64-encoded):**

```
base64 -i private-key.pem | pbcopy
kubectl edit secret secrets --namespace develocity-provenance-governor
```

Then, under `data:`:

```yaml
data:
  signing.key.MY_KEY_NAME.private-pem: <PASTE_BASE64_PRIVATE_KEY>
```

For the public key:

```shell
cat public-key.pem | sed 's/^/    /' | pbcopy
kubectl edit configmap properties --namespace develocity-provenance-governor
```

And under `data:`:

```yaml
data:
  signing.key.MY_KEY_NAME.public-pem: |
    -----BEGIN PUBLIC KEY-----
    ...
    -----END PUBLIC KEY-----
```

**Option C: Directory-Based Key Management (Recommended for Multiple/Rotating Keys)**

When managing multiple signing keys, consider organizing them in a `keys/` directory with descriptive, timestamped filenames for easy rotation:

```shell
mkdir -p keys/
cp private-key.pem keys/signing.key.20250401.private-pem
cp public-key.pem keys/signing.key.20250401.public-pem
```

Your keys directory should look like:

```text
keys/
  signing.key.20250401.private-pem
  signing.key.20250401.public-pem
```

Create the Kubernetes secret from all files in the directory:

```shell
kubectl create secret generic signing-keys \
  --from-file="keys/" \
  --namespace develocity-provenance-governor \
  --dry-run=client -o yaml > signing-keys-secret.yaml

# Review and apply
cat signing-keys-secret.yaml
kubectl apply -f signing-keys-secret.yaml
```

This method is ideal for organizations with multiple keys or scheduled rotations, allowing bulk updates and version tracking.

> [!TIP]
> Key Naming: Use a unique, date- or version-based key name (such as org1-20250315, signing-key-v3). Use the exact same key name for both private and public keys, and rotate as needed.

<a id="verifying-key-loading-in-logs"></a>

### Verifying Key Loading in Logs

After updating your secrets/configmaps and restarting the deployment, you should see logs such as:

```text
Signature support enabled, for key pair [name:MY_KEY_NAME:keyid:XXXXXX:signing-algorithm:ed25519]
```

Where `MY_KEY_NAME` matches your configured key, and `keyid` is a short digest fingerprint.

<a id="verifying-signing-keys"></a>

### Signature Validation and TrustedPublicKeys Policy

Simply signing attestations does **not** enable signature validation in policies: you must configure the set of trusted public keys.

> [!IMPORTANT]
> Validation requires a TrustedPublicKeys policy including your public key, even when evaluating attestations from the same instance.

To enable signature validation:

1.  Extract the public key PEM (from generation above).
    
2.  Create a TrustedPublicKeys policy and add your public key:
    

```yaml
apiVersion: policy.gradle.com/v1
kind: TrustedPublicKeys
metadata:
  name: acme-gov-signing-keys
spec:
  keys:
    org1-20250315:
      pem: |
        -----BEGIN PUBLIC KEY-----
        ...
        -----END PUBLIC KEY-----
```

1.  Deploy the policy to the `policies` ConfigMap.
    
2.  Restart the deployment.
    

Policy evaluation will only validate signatures from keys listed in the TrustedPublicKeys policy.

<a id="uploading-public-keys-to-artifactory-optional"></a>

### Uploading Public Keys to Artifactory (Optional)

If you are using Artifactory for attestation storage and wish Artifactory to verify signatures:

1.  Log in to Artifactory UI
    
2.  Go to **Administration** → **Security** → **Key Management** → **Public Keys**
    
3.  Click **Add Keys**, provide an alias (for human reference only), paste your public key
    
4.  Save the key; the cryptographic match uses the key ID, not the alias.
    

> [!NOTE]
> Artifactory uses the cryptographic key, not the alias, for attestation verification.