Model and Code Encryption for Federated Computing Scenarios
In highly regulated environments such as healthcare, pharmaceuticals, or finance, protecting model weights and code artifacts is essential—not just for data privacy and security, but also for safeguarding proprietary intellectual property. This article introduces a reproducible method for encrypting models and training logic within Rhino’s Federated Computing Platform (FCP). The code examples throughout the article are taken directly from the Secrets Manager Integration and Encryption with Rhino FCP to emphasize how to use it with the secret manager. It also provides NVIDIA FLARE Example - Encrypted Model Code and Weights, which demonstrates an alternate approach to encrypting without relying on a secret manager.
Prerequisites
Access to the Rhino FCP platform
Imported relevant dataset available in FCP
What You'll Learn
Encrypt code and model weights
Configure encrypted Federated Learning (FL) jobs in FCP
Use secret manager or manual key injection
Overview
To learn more about why you might need to use encryption and about the Rhino FCP encryption workflow, read the following subsections.
Why Encrypt in Federated Computing?
FL enables data to remain distributed across collaborators—but model artifacts can still leak sensitive information. FL systems are vulnerable to several types of attacks that can compromise privacy, security, and model integrity, including:
Intellectual property protection: Model weights and code artifacts are proprietary assets that encode valuable architectures and data patterns.
Poisoning attacks: Malicious clients inject harmful or biased updates into the model to degrade performance or introduce backdoors.
Inference attacks: Adversaries analyze shared model updates to recover sensitive patterns about training data.
Communication attacks: Attackers intercept, modify, or replay messages between clients and the server to compromise training integrity.
Free-riding attacks: Participants try to obtain the trained global model without actually contributing real local training.
If model parameters are exposed, they can leak sensitive data patterns, reduce competitive advantage, violate contracts, damage the resulting model’s integrity and commercial value, and expose the organization to regulatory penalties, legal liability, and reputational harm.
In addition, malicious participants may attempt to corrupt model updates, extract private data patterns from shared parameters, intercept communications, or contribute fake updates to gain access to the final model without legitimate participation. A detailed analysis of these attack types can be found in this paper.
How Does Encryption Happen?
This workflow applies when a collaborator has already trained a machine learning model outside of Rhino FCP and now needs to upload that model into Rhino for secure inference, fine-tuning, or federated training. In addition, encryption applies to storing final model weights after the training / fine-tuning process. This protects the artifact from leakage during upload or storage and satisfies compliance requirements in regulated environments like healthcare or finance.
Secure Key Handling Modes
Rhino supports two secure key handling modes for decrypting encrypted models at runtime. You may adapt these approaches to fit your own container build and encryption workflows. We generally recommend using a Cloud Secrets Manager for production workloads, as it offers automated, secure, and scalable key management. Alternatively, local JSON keyfiles can be used in development or non-cloud environments but require careful handling to maintain security.
Scenario #1: AWS Secrets Manager (automatic key management)
Rhino automatically retrieves the encryption key stored in AWS Secrets Manager and injects it into the container environment as a JSON file at runtime. This approach is ideal for production workloads due to its automation, security, and scalability. This article explains how to implement the workflow, in detail, using the Secrets Manager Integration and Encryption with Rhino FCP.
As of July 2025, Rhino supports AWS Secrets Manager as a productized integration, but also supports other secret managers through custom integrations.
Scenario #2: Manual JSON Keyfile:
The encryption key is stored in a JSON file that you manage yourself. You can add this file directly to your container image or provide it manually as a secret parameter at runtime through the Rhino UI. This article describes how to implement this alternative approach using the NVIDIA FLARE Example - Encrypted Model Code and Weights.
Note: Be sure to coordinate with your organization's IT or Cyber Security team to follow internal security protocols when managing encryption keys.
Scenario 1: Secrets Manager
The following directory structure shows the complete example used for all code samples in this scenario.
This scenario can be understood in two main groups of steps:
Code and Initial Model Provisioning Procedure — where the developers prepare and encrypt their model artifacts before upload.
Code Execution Procedure — inside Rhino Orchestrator, where the encrypted model is securely decrypted using the secret managed in the Secret Manager and used at runtime for inference or fine-tuning.
Code and Initial Model Provisioning Procedure
Encrypt code and model parameter files
Encrypt code and model parameter files (e.g., .pt→ .pt.enc).
Note: While encryption is performed outside Rhino (by the client or their CI/CD system), we include this step here to illustrate the process clearly for users. Customers should use their preferred encryption tools or KMS solutions (e.g., AWS KMS, Google Cloud KMS) to ensure artifacts are encrypted before upload.
Example command (adapted from a customer implementation):
Parameters:
-i- input file to be encrypted-o- encrypted output file, for NVFLARE, must end in.enc-k- key id of the secret in secrets manager (must match container name)-d- boolean flag to delete the original file to prevent it from being Packaged in the container
Build the container
Build the container with encrypted code and model.
Example Dockerfile line to include the encrypted model:
Code Execution Procedure
Edge Computation at Each Client
Decrypt the files using the secret and execute the code in the Trusted Execution Environment.
This is easily done by using the Rhino-provided decrypt_weights() function from decrypt_code.py, which is imported and called in infer.py.
The relevant part from infer.py:
The relevant part from decrypt_code.py:
Store
Store the encrypted global model in a workgroup storage bucket. This is a specific and isolated bucket that is private to the workgroup. Access to the stored model is controlled through Rhino Orchestrator, which manages secure communication with the Secrets Manager service.
encrypted_persistor.py shows how the server loads the RSA public encryption key to encrypt the aggregated model artifact before saving it back to the workgroup storage bucket:
Repeat process
For each federated round, Rhino Orchestrator securely retrieves the private key from the configured Secrets Manager and injects it into the container environment for use by the decryption logic. This process repeats each round, with clients decrypting (as elaborated in step 4) and training locally while the server aggregates and re-encrypts the global model.
This repetitive workflow ensures that pre-trained models can be brought into Rhino safely, without ever exposing sensitive model internals or private training patterns. The encryption and decryption steps are automated and isolated, providing strong protection with minimal friction to the developer.
Scenario 2: Manual Secret
This scenario describes how teams can manually manage and supply their encryption key without relying on an integrated Secrets Manager. NVIDIA FLARE Example - Encrypted Model Code and Weights demonstrates this approach in detail.
Unlike Scenario #1, there is no automated key retrieval. Instead, you generate and store the key yourself, then provide it manually at run time easily through the UI.
The following directory structure shows the complete example used for all code samples in this scenario:
(Highlighted files are the specific ones provided as examples throughout the workflow)
Similar to Scenario #1, this Scenario will be Understood in Two Main Groups of Steps
Code and Initial Model Provisioning Procedure — where the developers prepare and encrypt their model artifacts before upload.
Code Execution Procedure — inside Rhino Orchestrator, where the encrypted model is securely decrypted at runtime using the secret manually injected by the user and used for inference or fine-tuning.
Code and Initial Model Provisioning Procedure
These steps are performed by the developer before uploading to Rhino.
Generate Encryption Key
Unlike Scenario #1 (which retrieves a key from AWS Secrets Manager), you generate your own encryption key locally.
Example command using generate_key.py file from the full NVFlare example:
This produces a local key file that only you hold. (in this example — my_model_key)
Encrypt Model Code and Weights
Encrypt both your source code and trained model weights ahead of time so the raw files are never included in the container.
Example command:
Note: This step is conceptually identical to Scenario #1’s encryption step, but here you use your own locally stored key instead of a cloud KMS/Secrets Manager.
Build the Container Image
Before doing that, make sure again that it includes only the encrypted code and weights in the image:
Relevant line from the Dockerfile:
The raw unencrypted files are never included in the container image.
Code Execution Procedure
These steps occur inside Rhino Orchestrator when the federated run is launched.
Edge Computation at Each Client
Decrypt the encrypted code and model weights before training or inference using the secret that is manually provided at runtime.
Unlike Scenario #1, this decryption does not happen inside your Python model code (there’s no decrypt_weights() function). Instead, the container’s entrypoint.sh script automatically decrypts all .enc files at startup, before launching the training or inference process.
This command:
Reads the secret key from
/input/secret_run_params.jsonDecrypts the
.encfile using Fernet symmetric encryption from the decrypt_code.py file.Writes the decrypted
.pyfile to the specified location inside the container
Aggregation and Encryption
After each federated training round, Rhino Orchestrator aggregates the updates received from all participating clients to produce a new global model. Before storing or sharing this model, the server encrypts it using a hybrid RSA–AES scheme with the public key manually provided at the beginning through the UI before hitting RUN.
Store
Store the encrypted global model in the workgroup’s private bucket within Rhino Orchestrator. This is a specific and isolated bucket that is private to the workgroup. Access to this storage is governed by workgroup-level permissions, ensuring that only approved users and processes can retrieve or manage the encrypted artifacts.
Repeat process
For each federated training round, this workflow repeats in the same way: the server distributes the encrypted global model to participating clients. Each client decrypts the model locally using the manually provided key (supplied at runtime), trains on its private data, re-encrypts the updated weights with the same key, and sends them securely back to Rhino Orchestrator. This cyclical process ensures robust security and consistent protection of model artifacts across all rounds of federated learning.
This repetitive workflow ensures that pre-trained models can be brought into Rhino safely, without ever exposing sensitive model internals or private training patterns. The encryption and decryption steps are automated and isolated, providing strong protection with minimal friction to the developer. However, the secret handling is done manually by the user which can reduce the overall security of this process.
Thanks again for investing your time in learning how to use the FCP in this use case, we can't wait to see what you will do with it! If you need support at any time, reach out to us at Rhino Support.
Additional Resources
This is an additional manual-encryption example that is provided in the Rhino user-resources repository:
Generalized Compute Example – Run Encrypted Code
This example shows a simpler GC approach to encrypt and decrypt only a specific file you define, rather than the entire container. It explains how to encrypt the file, decrypt it at runtime with a secret, and run the code securely.
Was this helpful?