From 2de7ce99c5f9655028392531f4867993ced50f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Wed, 22 Nov 2023 12:29:06 +0200 Subject: [PATCH] chore(docs): improve on password hashing (#6951) --- docs/docs/concepts/architecture/secrets.md | 25 +++++++++++++++++++++- proto/zitadel/management.proto | 2 +- proto/zitadel/user/v2beta/password.proto | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/docs/docs/concepts/architecture/secrets.md b/docs/docs/concepts/architecture/secrets.md index 47b1567f65..4bfe0af9ec 100644 --- a/docs/docs/concepts/architecture/secrets.md +++ b/docs/docs/concepts/architecture/secrets.md @@ -58,9 +58,32 @@ ZITADEL does handle many different passwords and secrets. These include: - Client Secrets :::info -ZITADEL uses `bcrypt` by default to store all Passwords and Client Secrets in an non reversible way to further reduce the risk of a Secrets Storage breach. +ZITADEL hashes all Passwords and Client Secrets in an non reversible way to further reduce the risk of a Secrets Storage breach. ::: +Passwords and secrets are always hashed with a random salt and stored as an encoded string that contains the Algorithm, its Parameters, Salt and Hash. +The storage encoding used by ZITADEL is Modular Crypt Format and a full reference can be found in our [Passwap library](https://github.com/zitadel/passwap#encoding). + +The following hash algorithms are supported for user passwords: + +- argon2i / id[^1] +- bcrypt (Default) +- md5[^2] +- scrypt +- pbkdf2 + +[^1]: argon2 algorithms are currently disabled on ZITADEL Cloud due to its steep memory requirements. +[^2]: md5 is insecure and can only be used to import and verify users, not hash new passwords. + +:::info +ZITADEL updates stored hashes when the configured algorithm or its parameters are updated, +the first time verification succeeds. +This allows to increase cost along with growing computing power. +ZITADEL allows to import user passwords from systems that use any of the above hashing algorithms. +::: + +Client Secrets always use bcrypt. + ### Encrypted Secrets Some secrets cannot be hashed because they need to be used in their raw form. These include: diff --git a/proto/zitadel/management.proto b/proto/zitadel/management.proto index 53caf0c2af..37f7c12b20 100644 --- a/proto/zitadel/management.proto +++ b/proto/zitadel/management.proto @@ -7755,7 +7755,7 @@ message ImportHumanUserRequest { string value = 1 [ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { example: "\"$2y$12$hXUrnqdq1RIIYZ2HPytIIe5lXdIvbhqrTvdPsSF7o.jFh817Z6lwm\""; - description: "Encoded hash of a password in Modular Crypt Format: https://passlib.readthedocs.io/en/stable/modular_crypt_format.html" + description: "Encoded hash of a password in Modular Crypt Format: https://zitadel.com/docs/concepts/architecture/secrets#hashed-secrets" } ]; reserved 2; // was algortithm, which is actually obtained from the encoded hash diff --git a/proto/zitadel/user/v2beta/password.proto b/proto/zitadel/user/v2beta/password.proto index c019bde098..8a615657ed 100644 --- a/proto/zitadel/user/v2beta/password.proto +++ b/proto/zitadel/user/v2beta/password.proto @@ -27,7 +27,7 @@ message HashedPassword { (google.api.field_behavior) = REQUIRED, (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { example: "\"$2a$12$lJ08fqVr8bFJilRVnDT9QeULI7YW.nT3iwUv6dyg0aCrfm3UY8XR2\""; - description: "\"hashed password\""; + description: "\"Encoded hash of a password in Modular Crypt Format: https://zitadel.com/docs/concepts/architecture/secrets#hashed-secrets\""; min_length: 1, max_length: 200; }