Use secret key in code but do not want to have it readable on a repo, best practice?

Hi,

I am working on data encryption. It is necessary to pass a secret key as an argument. I would like this key not to appear in the code as it will then be on a repository. Do you know the best practices for this kind of case, please?

you can put it in a file, then read that file when needed. it can even be at compile time with things like include(_str|_byte)?!.
make sure to gitignore it

Ok. Then I have multiple server to launch. Maybe a conf file, never committed by server and that must be asked if needed by someone who is working on the branch.

I disagree with this. Secrets should never be part of the code nor the binary.
Secrets should be loaded from external sources by the binary during runtime only.
Not long ago we had a scandal here in Germany due to a developer exploiting a vulnerability in a software, which stored credentials in the binary.
Don't do that!

Well, in cloud stuff you'd use something like Cloud Secrets Management - AWS Secrets Manager - AWS or https://azure.microsoft.com/en-us/products/key-vault

Without using amazon service, so store data in data base and get it encrypted by network, and decrypt when using it ?
During a test for a interview, they say that I should have use a secret key mecanism. I was wondering how because, you always have finaly to get it from somewhere and the algo need it to work.

Something like that.

The ideal is "Hardware Security Modules" (HSM) which is a physical device that internally generates and stores the key and it never leaves, meaning the data that needs to be encrypted (or decrypted, signed, etc) needs to be sent to it.

These are provided by cloud services as Key resources you send network requests to, or for physical servers they are often a dongle that is plugged in (and the rack is padlocked) that you access using OS APIs.

You can fall back to progressively less bulletproof equivalents: CPU secure enclaves, OS provided keychain services, etc., all the way down to an environment-variable provided password for a file fetched on provisioning that is only read by a separate process you IPC with. If you're any simpler than that you're not really doing anything at all if there's a memory safety type concern (explicit cryptography libraries are still needed for side channel attacks, but generally those go with any of these approaches), though even that is not what I would consider acceptable in anything less than dire circumstances.

This does imply a pretty rough throughout limitation; the general solution for encryption is for your protocol to derive a temporary (often symmetric) key from the persistent key you can use locally, which must be cycled regularly so it's less of a concern if it does get leaked (most memory-related exploits are not particularly fast, so if you cycle every few minutes you're far better off than if the persistent encryption key got leaked). This is not simple to do reliably and safely, though!

It's generally easier for signing; these only need a digest (eg SHA) of the content which is the same regardless of the data size, so if the number of signatures stays reasonable you're fine.

Reasonable here depends on the hardware; but I've seen numbers generally in the GB/s so not a big concern for a single server. If you're Google things get harder, as usual.

Thank you a lot for your time. I will read more about what you send and say me.

I store all kinds of secrets in command line tool pass, which encrypts them with gpg.

You can then either pipe the secret with pass show <secret> | <yourcommand>, provide it as an argument with <yourcommand> $(pass show <secret>) or copy the secret to your clipboard with pass -c <seceret> and paste it on a prompt or in a form.

I keep my password store in a separate local git repository that I autoshare with all my devices.

Once in the past we as a team shared an airgapped secret key encrypted with our gpg public keys.

As others said: I would not store any secret (encrypted or otherwise) with the code.

As already said above: secret keys are not contained in code (neither source or binary), they are separate artifacts.
In case you produce hardware, these are typically created during production in the factory and stored on the hardware device that you produce - e.g. in an HSM or TEE or similar.
Ideally the key generation is already done in the HSM/TEE and never leaves this - only the public key goes out of the security module.
Some usecases require to inject a private key into the device. In this case, one has to encrypt the data transfer from a secure key server to the HW device you are assembling.

There are always exceptions in real life. When prototyping on ESP32, I needed to embed my WiFi password in the binary, using include_str! and a gitignored file. But I agree this is special to embedded and should not be done on computers in general.

If you use this pattern, however, ensure it is documented somewhere, including the expected format. There may be a file password included in the git tree with a dummy password and a comment, and the user would need to create a (already gitignored) file password.local which is included by the code. Also make sure there is no default password and the code won't compile without the custom file, so there is no risk someone goes in production with the dummy password. (this paragraph still applies to config files parsed at runtime)

For desktop apps, it is better to use an OS API:

For the cloud services, see scottmcm's comment.

Poorman's solution is an .env file that is never commited to VCS.

And one more thing: do not use shared keys: generate private/public key pair instead