Encrypting passwords instead of hashing?

I was reading the admin’s manual in nextcloud’s documentation and read:

The user password is also stored encrypted in the Nextcloud database. For encryption of the password, the token and an instance-specific secret is used.
[
]
An actor with access to the access token, the Nextcloud config file, and the Nextcloud database can decrypt user passwords stored in the database.

I was wondering why is this the case and the passwords are not just hashed using Argon2id + Salt or some other similar standard secure setup.

I don’t know if there’s a reason for this but it just seems like an unnecessary security problem.

I was wondering why is this the case and the passwords are not just hashed using Argon2id + Salt or some other similar standard secure setup.

The current documentation is ambiguous and outdated in this area. I’ll see what I can do about that, but to respond briefly to your specific question:

Disclaimer: This has not been peer-reviewed, but I believe it is broadly accurate based on my reading of the underlying code.

Nextcloud does use standard one-way password hashing for account authentication when using its built-in database backend. It prefers Argon2id when supported by PHP, with Argon2i or bcrypt as fallbacks.

The encrypted password mentioned in the manual is a separate, recoverable copy stored in association with a server-side authentication-token record. When auth.storeCryptedPassword is enabled – which it is by default – and the login password is available to Nextcloud, this copy may be stored for features that need the original credential, such as external storage access. A one-way Argon2id hash cannot support those uses because the original password cannot be recovered from it.

I don’t know if there’s a reason for this but it just seems like an unnecessary security problem.

It does represent a security-versus-functionality tradeoff. Administrators can disable the behavior if they do not require the associated functionality. The current documentation is unclear because it does not distinguish the one-way account-password hash from the reversibly encrypted copy associated with an authentication-token record.

Your post nudged me to start drafting a revision of that section that makes this distinction explicit and attempts to clarify/update some other related details. I’ll submit a PR to the documentation repository shortly to get further review and feedback.

Passwords generally shouldn’t be encrypted at all. Hashing with a slow, password-specific algorithm like Argon2id is the safer approach, since the original password can’t be recovered if the database is compromised.

There is an open pull request with more details:

Please check out, if that clarifies the situation for you