NOTICE: All information contained herein is, and remains
the property of TechnoCore.
The intellectual and technical concepts contained
herein are proprietary to TechnoCore and dissemination of this information or reproduction of this material
is strictly forbidden unless prior written permission is obtained
from TechnoCore.
The ObjEncrypt class provides core functionalities for handling encryption and decryption of data within the platform. It includes methods for provisioning encryption keys for different packages and for encoding entire database tables based on configuration settings.
The module also features a powerful command-line interface (CLI) for direct interaction with the encryption functionalities.
ObjDatatyper, rich__init__(self, DB=0)The constructor for the ObjEncrypt class. It simply calls the parent ObjData constructor.
encode_table(self, table="", crypt_cols=[], key_cols=[])Encrypts specified columns within a single database table.
crypt_cols. The key_cols are used to build the WHERE clause for the UPDATE statement, ensuring the correct row is targeted.table (str): The name of the table to process.crypt_cols (list): A list of column names to encrypt.key_cols (list): A list of column names that form the primary key for identifying rows.encode_tables(self, package="")Encrypts columns for multiple tables as defined in the global configuration.
config.yaml (datastore.encryption section) and calls encode_table for each one.provision(self, package="")Provisions PEM keys (public and private) for a specified package.
def_package table, making it available to other systems.clear_key_cache(self, package=None)Clears cached encryption keys to force reloading from Infisical or disk.
package (str, optional): Package name to clear cache for. If None, clears all cached keys.# Clear cache for specific package
enc = ObjEncryption()
enc.clear_key_cache("homechoice")
# Clear all cached keys
enc.clear_key_cache()
Encryption keys are cached in memory for performance with automatic time-to-live (TTL) expiration:
EncryptionConstants.KEY_CACHE_TTL seconds (default: 3600 seconds / 1 hour)clear_key_cache() to force immediate reloadclear_key_cache() to bypass TTL and force reloadThis ensures:
clear_key_cache()The ObjEncryption.py script provides a CLI for easy access to the encryption and decryption functions, with styled output provided by the rich library.
encryptEncrypts a string of text.
python3 factory.core/ObjEncryption.py encrypt "my secret text" --package "my_package"
text (str, required): The text to encrypt.--package / -p (str, optional): The package context to use for encryption. If omitted, the default package is used.decryptDecrypts an encrypted string.
python3 factory.core/ObjEncryption.py decrypt "^encrypted_string_data" --package "my_package"
text (str, required): The encrypted text to decrypt.--package / -p (str, optional): The package context to use for decryption. If omitted, the default package is used.provisionProvisions encryption keys for a package.
python3 factory.core/ObjEncryption.py provision "my_package"
package (str, required): The name of the package to provision keys for.encode-tablesRuns the full table encoding process.
python3 factory.core/ObjEncryption.py encode-tables
datastore.encryption section of the configuration file.When Infisical is enabled, PEM keys can be stored in the secret
manager instead of (or in addition to) local files in data.config/.
For load_public_key(), load_private_key(), has_private_key(),
and has_public_key():
_public_keys / _private_keys)PEM__{PACKAGE}_{TYPE})data.config/{package}_{type}.pem)If Infisical is unavailable, the system falls back silently to
file-based keys.
| File on disk | Infisical secret name |
|---|---|
homechoice_private.pem |
PEM__HOMECHOICE_PRIVATE |
homechoice_public.pem |
PEM__HOMECHOICE_PUBLIC |
base_private.pem |
PEM__BASE_PRIVATE |
reference_public.pem |
PEM__REFERENCE_PUBLIC |
Use the migration tool to upload existing PEM files:
# Preview
python factory.deploy/ObjSecretMigrate.py push-keys --dry-run
# Push all keys
python factory.deploy/ObjSecretMigrate.py push-keys
# Custom key folder
python factory.deploy/ObjSecretMigrate.py push-keys --key-folder /path/to/keys
Once keys are in Infisical, they are used automatically. Local
files can be kept as fallback or removed from non-production
machines.
A package that has no PEM keypair of its own falls back to its
archetype's keypair. The archetype is read from
config.yaml <package>.archetype (via
ObjEncryption._package_archetype, which reads
Objects.global_config.config directly — get_ini_value only merges
the base + active-package sections and cannot see an arbitrary
package's archetype).
So a fullhouse-archetype package such as pims transparently reads
the shared fullhouse_private.pem / fullhouse_public.pem instead of
requiring its own keys (and passing the Encryption PEM Files preflight
check, which reports ... via fullhouse).
Resolution order per package: module cache → Infisical → own file →
archetype (recursing once into the archetype). The fallback is applied
on-miss — the own-package path (cache/Infisical/own file) is
unchanged, so key lookups for a package that does have its own key
behave exactly as before. The read/probe methods honour the fallback
(load_private_key, load_public_key, has_private_key,
has_public_key, get_public_key_text); the write paths
(generate_key, save_key, provision) never do — a newly minted key
is always written under the package itself.
The ObjEncryption module has comprehensive test coverage for key management and Infisical integration.
| Test Suite | Tests | Type | Purpose |
|---|---|---|---|
test_ObjEncryption_keys.py |
34 | Unit | PEM key storage/retrieval, Infisical integration, file fallback, caching, archetype fallback |
| Total | 34 |
# Run all ObjEncryption tests
pytest resource.test/pytests/factory.core/test_ObjEncryption_keys.py -v
# Run specific test class
pytest resource.test/pytests/factory.core/test_ObjEncryption_keys.py::TestLoadPemFromInfisical -v
encrypt_envelope(plaintext, package) -> {key, iv, ct} and
decrypt_envelope(envelope, package) -> plaintext provide AES-256-GCM +
RSA-OAEP-SHA256 hybrid encryption for payloads too large for raw RSA (e.g.
form bodies). The body is AES-GCM encrypted under a random key; that key is
RSA-OAEP wrapped with the package public key. All three fields are base64.
These are byte-compatible with the browser's WebCrypto (RSA-OAEP/SHA-256
AES-GCM), so resource.web/javascript/axion.formcrypt.js encrypts andWebPageForm.process_submit (_maybe_decrypt_envelope) decrypts with no shareddecrypt_envelope raises on a missing key or GCM auth-tag failuretest_ObjEncryption_envelope.py. Used by form-submission<pkg>.forms.encrypt).