Kubo private key encrypted at rest?

Hi, I’m trying to control Kubo with my application. I want to add some Orbitdb in a Kubo plugin. I like Kubo as a separate process for process isolation.

I have an encrypted at rest requirement, so I’d like the config to be passed to Kubo on startup.

I coded Kubo to take the config file from an ENV var, but got stuck encoding the identity into the config using const peerId = await createEd25519PeerId()

It didn’t work. I noticed in the documentation here:

It says “Ipfs will always generate the peerID from its keypair at runtime.”

How does it do that without the info in the config?

How can I configure a Kubo instance with it’s private data encrypted at rest?

Thank you

No it’s not encrypted at rest.

The PrivKey field in the config json file contains the plain text private key.

There is no such feature implemented to encrypt private data.
The first question to implement such feature is with what key is the private key gonna be encrypted with ? Do you expect Kubo to prompt you for a passphrase everytime you start ipfs daemon ?

Hi, Jorropo, thanks for taking the time to answer.

I’m happy to collaborate on making this a Kubo feature. If it’s not appropriate as a feature, I’ll hack my own copy.

Are there any other places Kubo stores private info besides the config file and keystore?

No it’s not encrypted at rest. The PrivKey field in the config json file contains the plain text private key.

Yes, with Kubo’s current design, any program with access to the user’s home directory can steal their identity by searching text files.

There is no such feature implemented to encrypt private data.

Bummer. Luckily, I can create!

The first question to implement such feature is with what key is the private key gonna be encrypted with ? Do you expect Kubo to prompt you for a passphrase everytime you start ipfs daemon ?

No, that’s not my use case, but I see how it could be added to Kubo, and I’d be interested in collaborating to create encryption at rest for all Kubos.

Programs ask for a password to generate a hash. That hash is used as a symmetric encryption key. To be secure, a “salt” is added to the password. This salt prevents “rainbow” attacks. The salt needs to be stored in the clear.

My program’s UI already asks for a password, salts, hashes, and uses the hash to decrypt a sqlite3 database. So I just need to pass the symmetric key.

My first plan was to just send the kubo config as an env var. This can be done by modifying Kubo’s serializer.

This prevents the config from being written to disk, but it’s a broken design because:

  • the config file isn’t the only secret data
  • ‘ipfs init’ doesn’t understand.

So I need a new design. So far, I have the config file and the Keystore for secrets.

I don’t think the DataStore needs encryption because content is secured in the application layer or unencrypted by design.

If Kubo wanted it’s own first-class encryption-at-rest feature, it might include some use cases like this:

  • Kubo boots and finds symmetric key in IPFS_PASSWORD_HASH.

    • Use it to decrypt “config.crypt” and keystore. Clears env var after reading
    • “Kubo init” accepts IPFS_PASSWORD_HASH during configuration
      • writes an empty config, an encrypted config.crypt, and encrypted stores
      • Can’t operate without IPFS_PASSWORD_HASH
  • Kubo boots and finds only salt in it’s config file.

    • Asks user for a password.
    • Hash password and salt for symmetric key
    • Use it to decrypt “config.crypt” and keystore.
    • ‘ipfs init’ has parameter to request password. Writes salt to config.

These two use cases aren’t interchangeable, but would cover most use cases.

Super long post! You read this far, what do you think?

Your plan seems good to me, I wouldn’t use custom hash thing I would use pbkdf2 as it’s the standard for that usecase.

I think the https://berty.tech team have a similar feature where they use a password to lock an sqlite store which is used by their kubo install or something similar.

Yes! Thanks for the tip for berty.tech. I’ll check that out.

pbkdf2 was designed in the 90’s before graphics card hashing, and for a single password hash can be defeated by existing programs with commodity hardware.

Argon2 was the winner of the password hashing competition and add memory complexity and threads. For a single-password system, it’s much more secure.

Either algorithm converts the password to a hash. For backwards security, I’d pass a sha256 of an argon2 hash in the env var to kubo.

If Kubo implements it’s own encryption-at-rest feature, I’d recommend argon2.

Thanks for the help Jorropo!

I’m not convinced of the general argument that hashes should be expensive as this is only linear cost increase for the attacker.

Please use a long passphrase as this has exponential scalling but I get few people do.

Obligatory:


Mb for calling PBKDF2 standard, yeah we do much “better” now.

1 Like

Bingo! GitHub - berty/go-ipfs-repo-encrypted: an encrypted ipfs repo using sqlcipher and go-ds-sql

1 Like