Wikantik prioritizes the security of user data and system integrity through robust cryptographic practices. The core logic for these operations resides in the wikantik-util module within CryptoUtil.java.
Wikantik uses salted password hashing to protect user credentials. When a user creates or updates a password, the system generates a random salt, combines it with the password, and hashes the result.
The system supports two hashing formats, prefixed for identification:
{bcrypt} (Current default): Used for new and re-hashed passwords. The work factor is 12 (DEFAULT_BCRYPT_COST), roughly 150 to 250 ms per hash on current hardware, and it is embedded in each stored hash, so raising it later affects only newly written hashes. Passwords longer than 72 bytes are truncated, as bcrypt does. A legacy hash is transparently re-hashed to bcrypt on the owner's next successful login.{SHA-256} (Legacy, still verifiable): Salted SHA-256, kept working so existing accounts migrate transparently rather than being locked out.Salted SHA-1 ({SSHA}) and unsalted SHA-1 ({SHA}) are no longer supported — a
stored value in either format never verifies, and it is left untouched (not
migrated) on a failed attempt.
A bcrypt entry is stored as {bcrypt} followed by the standard $2a$ bcrypt string, which carries its own salt and cost. A legacy {SHA-256} entry is the Base64 encoding of the hash followed by the salt. The algorithm prefix lets CryptoUtil.verifySaltedPassword choose the matching verification logic.
New passwords are checked by PasswordValidator, which follows NIST 800-63B: length rather than composition rules, plus a blocklist of common passwords. The settings are wikantik.password.minLength (default 8), wikantik.password.maxLength (default 128) and wikantik.password.blocklist.enabled (default true). Repeated failed logins are slowed per account by wikantik.login.throttling (default true).
Wikantik has its own bearer API keys and also holds credentials for a few external services.
/tools/*): A key is wkk_ followed by 32 random bytes (base64url) from a SecureRandom. Only its SHA-256 hash is stored, in the api_keys table; the plaintext is shown once, when the key is created. SHA-256 rather than bcrypt is deliberate: the token carries 256 bits of entropy, so a slow hash adds cost without protection. Each key has a scope (mcp_read, mcp_admin, tools or all), and issuing a key is written to the audit log (as are rotation and revocation through the self-service Preferences page). See Connecting Claude Code to the Wikantik MCP Servers for the client side and docs/admin/ApiKeys.md for the admin reference.ANTHROPIC_API_KEY from the JVM environment. A local Ollama backend needs no key.mail.smtp.* properties or a JNDI mail/Session resource (see wikantik.mail.jndiname) with whatever credentials your relay (Brevo, SendGrid, Amazon SES and so on) issues.wikantik.indexnow.apiKey for IndexNow pings, and the SSO client secret and SAML keystore passwords under wikantik.sso.*.ANTHROPIC_API_KEY) which are read by the system at runtime.ROOT.xml) to inject sensitive configuration into the application.Wikantik is designed to run behind a TLS-terminating reverse proxy (like Nginx, Apache, or Cloudflare).
https where available.web.xml marks the JSESSIONID cookie HttpOnly and cookie-only (no URL rewriting) so script injection cannot read it. It deliberately does not set Secure, because the right value depends on the deployment. Secure is applied only when Tomcat knows the request arrived over HTTPS, either because TLS reaches Tomcat directly or because the proxy sends X-Forwarded-Proto: https and the RemoteIpValve is configured to read it. The Tomcat context template also sets SameSite=Lax.wikantik.cookieAuthentication is on (default off), the WikantikUID cookie is HttpOnly, SameSite=Lax and Secure on HTTPS, and holds an opaque, server-validated token.STSFilter adds a Strict-Transport-Security header to responses.Cluster Hub: Wikantik Platform Development Hub: Architecture, MCP Protocols, and Agent Briefings (wikantik-development)