# Re-encryption in Nexus Repository

Nexus Repository uses a static key for reversible encryption to store sensitive data. Secrets refer to sensitive configuration values such as API keys, SAML passwords, and other credentials. We recommend administrators change their encryption key used for secrets from the default value to enhance their repository security.

## FIPS 140-3 Compliance

For FIPS compliance, all key-passwords used must have at least 112-bit complexity. These must also use a more secure encryption algorithms which will need to be updated. Secrets are complemented by an API key, which is encrypted with the same mechanism. By default, secrets use a password and salt that are not FIPS compliant, so configuring fixed encryption is required.

See [FIPS 140-3 Compliance](https://help.sonatype.com/en/nexus-repository-fips-140-3-compliance.html) documentation for details.

## Re-encryption Health Check

The following health check warning displays when the default encryption key has not been updated. Use this guide to re-encrypt your secrets to resolve the warning.

```
Nexus was not configured with an encryption key and is using the Default key
```

## Best Practice When Upgrading

The Nexus Repository upgrade involves applying database scripts to change the schema which the re-encryption mechanism depends on. We recommend avoiding making changes to the encryption while performing an upgrade.

Perform the re-encryption outside of your regular upgrade maintenance plan.

## Changing the Encryption

When you already have an encryption configuration file with a fixed encryption and need to update the keys, you must also provide the previous encryption details under the `previousFixedEncryption` section. Ensure your existing configuration uses secure parameters as defined by FIPS.

## Steps for Re-Encryption

1. #### Deploying in High Availability (HA) Environments (optional)

Deploying to HA environments require that the key used for encryption is available to all nodes before the re-encryption process is triggered.

Review the [High Availability (HA) Deployments](https://help.sonatype.com/en/re-encryption-in-nexus-repository.html#high-availability--ha--deployments) section below

2. #### Create a JSON File Containing Your Custom Encryption Key

For improved security and to simplify deployment of your custom encryption keys, they are stored in a external json file which is referenced by your runtime configuration.

See [Create a JSON for Custom Encryption Key](https://help.sonatype.com/en/configuring-the-runtime-environment.html#create-a-json-file-containing-your-custom-encryption-key)

3. #### Add the Secrets File to the Nexus Repository Configuration

The Nexus Repository runtime must include the secrets file during the initial startup. The active key configured in the secrets file is when re-encrypting secrets.

See [Use a Secrets File to the Nexus Repository Configuration](https://help.sonatype.com/en/configuring-the-runtime-environment.html#use-a-secrets-file-to-the-nexus-repository-configuration)

4. #### Set the Active Encryption Key API

Use the API to set the active encryption key stored in your secrets file.

See the [Set the Active Encryption Key API](https://help.sonatype.com/en/re-encryption-in-nexus-repository.html#set-the-active-encryption-key-api)

5. #### Execute the Re-Encryption API

After setting the active encryption key, execute the API to re-encrypt existing secrets and stored encrypted data using the active key.

See the [Re-Encrypt the API Keys Table](https://help.sonatype.com/en/re-encryption-in-nexus-repository.html#re-encrypt-the-api-keys-table) section below.

## Configurable Encryption Iterations

Nexus Repository supports configuring the number of iterations used when encrypting passwords and secrets. These settings allow you to control the strength of PBKDF2-based encryption. This configuration is defined in the `nexus.properties` file and applies to two separate areas:

- User password encryption
- Secrets and principals encryption

The encryption iteration properties work in conjunction with their corresponding algorithm properties. Both values must be considered together when configuring encryption behaviour.

Changing the algorithm or iteration value affects how new data is encrypted. Existing data may require re-encryption, depending on the encryption context.

### Password Encryption Iterations

The `nexus.security.password.iterations` property controls the number of iterations used when encrypting user passwords.

When a user successfully logs in, Nexus Repository checks whether the stored password matches the currently configured algorithm and iteration count. If it does not match, the password is automatically re-hashed using the new settings. No manual migration step is required for passwords.

Password encryption is determined by the configured algorithm and iteration settings.

- `nexus.security.password.algorithm`: Defines the encryption algorithm used for passwords. The default value is `shiro1`

- `nexus.security.password.iterations`: Defines the number of iterations used by the configured algorithm. The default value varies by algorithm.

Nexus Repository uses default values for the configured algorithm if values are not specified. The default values are:

| Algorithm | Iterations | Notes |
| --- | --- | --- |
| `shiro1` | 1024 | Iterations are not configurable |
| `PBKDF2WithHmacSHA1` | 1024 | Configurable |
| `PBKDF2WithHmacSHA256` | 10000 | Configurable |

Example:
```
nexus.security.password.algorithm=PBKDF2WithHmacSHA256
nexus.security.password.iterations=12000
```

### Secrets and Principals Encryption Iterations

The `nexus.security.secrets.iterations` property controls the number of iterations used when encrypting secrets and principals, such as API keys.

Secrets and Principals encryption is controlled by the following properties:

- `nexus.security.secrets.algorithm`: Defines the encryption algorithm used for secrets. The default value is `PBKDF2WithHmacSHA1`

- `nexus.security.secrets.iterations`: Defines the number of iterations used by the configured algorithm. The default value varies with algorithm.

Changing this configuration does not automatically re-encrypt existing secrets. Newly created secrets use the updated iteration value and Existing secrets continue to use their original encryption settings until re-encrypted manually. See [Re-Encrypt the API Keys Table](https://help.sonatype.com/en/re-encryption-in-nexus-repository.html#re-encrypt-the-api-keys-table) to re-encrypt manually.

Nexus Repository uses a default iteration count based on the configured secrets algorithm

| Algorithm | Iterations |
| --- | --- |
| PBKDF2WithHmacSHA1 | 1024 |
| PBKDF2WithHmacSHA256 | 10000 |

Example:
```
nexus.security.secrets.algorithm=PBKDF2WithHmacSHA256
nexus.security.secrets.iterations=12000
```

## Mandatory Re-Encryption

When you change the encryption configuration, data created after the change uses the new configuration. Existing data remains encrypted with the previous configuration. To keep your data consistent, re-encrypt existing data after any configuration change.

Encrypted data exists in two tables:

- `secrets`: Stores the encrypted values and the metadata used to encrypt them.

- `apikeys`: Encrypts data using fixed configuration values and doesn’t store encryption metadata.

Whenever there is a change to the encryption configuration, you must run the following tasks to re-encrypt the existing data:

1. Re-encrypt the secrets table to set the active encryption key
2. Re-encrypt the API Key table when you change the `fixedEncryption` block or the algorithm.

### Set the Active Encryption Key API

Use the following API call to trigger a task to re-encrypt existing secrets using your custom encryption key.

```
PUT /service/rest/v1/secrets/encryption/re-encrypt
```

The request body includes the following parameters:

- `secretKeyId` - The ID of the new encryption key as it appears in the secrets file.
- `notifyEmail` (Optional) - An email address to receive a notification about the task result (requires email service configuration).

A successful request schedules a re-encryption task with the task ID in the response body.

```
curl -u "admin" -X 'PUT' \
  'https://<your-instance-url>/service/rest/v1/secrets/encryption/re-encrypt' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "secretKeyId": "string",
  "notifyEmail": "string"
}'
```

**Warning**

Interrupting the re-encryption task may leave secrets encrypted with the old key. Fix this by resending the API call and allowing the task to complete.

### Re-Encrypt the API Keys Table

Run this task only when you change the `fixedEncryption` block or the encryption algorithm. Use the following API call to trigger a re-encryption task.

```
PUT /service/rest/v1/apikeys/encryption/re-encrypt
```

A successful request schedules a re-encryption task with the task ID in the response body.

```
curl -u "admin" -X 'PUT' \
  'https://<your-instance-url>/service/rest/v1/apikeys/encryption/re-encrypt' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  “algorithmForDecryption”: “Algorithm used before the change“
}'
```

**Optional Parameters:**

- `algorithmForDecryption`: The algorithm used to decrypt existing secrets. This is necessary if you have used custom parameters in the previous algorithm.
- `iterationsForDecryption`: The iteration count used when secrets were encrypted in the previous configuration.
- `notifyEmail`: An email address that receives notification when the task completes.

Example:
```
curl -u "admin" -X 'PUT' \
  'https://<your-instance-url>/service/rest/v1/apikeys/encryption/re-encrypt' \
  -H "Content-Type: application/json" \
  -d '{
    "algorithmForDecryption": "PBKDF2WithHmacSHA1",
    "iterationsForDecryption": 1000,
    "notifyEmail": "admin@example.com"
  }'
```

### Scenarios

Below are the scenarios (but not limited to) that require both tasks.

- Set `fixedEncryption` block details: When you change default values in the `fixedencryption` block, you must run both the tasks.
- Changing the Algorithm: If you change the encryption algorithm, you must run both the tasks.
- Updating the `fixedEncryption` values: If you change the default `fixedEncryption` parameters, run both the tasks. For the _apikeys_ task, include the `previousFixedEncryption` block when you are already using custom `fixedEncryption` values. You do not need to include `previousFixedEncryption` if you are configuring the `fixedEncryption` block for the first time.

## High Availability (HA) Deployments

In a HA cluster all Nexus Repository nodes require access to the secrets found in the JSON file

When using rolling restarts in an HA cluster, temporarily set the `active` key to `null` for the first restart. This is necessary as the nodes do not have access to the new key until they are restarted. The secrets file must be accessible by the nodes or the re-encryption task fails.

This allows the nodes to come up with the new secrets file without attempting to use an inactive key. Once all nodes are up, activate the new key using the API, and update your secrets file to reflect this change for subsequent restarts.

1. #### Deploy the secrets file

Create a JSON file containing your custom encryption key. For the first restart, set the "active" key to null as the nodes initially won't have access to the new key.

All the Nexus Repository nodes require access to the JSON file.

2. #### Rolling restart

Perform a rolling restart of your Nexus Repository instances. This means restarting each node one by one, allowing the others to continue running and maintain service availability.

3. #### Activate the new key

Once all nodes have restarted and are running with the new secrets file, you need to activate the new encryption key using the REST API endpoint. Provide the `secretKeyId` that matches the id in your secrets file.

4. #### Update the secrets file

After successfully re-encrypting, update your secrets file and set the "active" key to your `secretKeyId`. Restart the cluster to use the new key without requiring the API call.
