<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Bartol Benjak</title>
    <description>The latest articles on Forem by Bartol Benjak (@bartol00).</description>
    <link>https://forem.com/bartol00</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3652397%2Fba877d82-b8ee-44c3-b4bc-b56193aa231e.png</url>
      <title>Forem: Bartol Benjak</title>
      <link>https://forem.com/bartol00</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bartol00"/>
    <language>en</language>
    <item>
      <title>SeguraPass: A Zero-Knowledge, End-to-End Encrypted Password Manager Built in Java</title>
      <dc:creator>Bartol Benjak</dc:creator>
      <pubDate>Wed, 10 Dec 2025 17:31:13 +0000</pubDate>
      <link>https://forem.com/bartol00/segurapass-a-zero-knowledge-end-to-end-encrypted-password-manager-built-in-java-4nij</link>
      <guid>https://forem.com/bartol00/segurapass-a-zero-knowledge-end-to-end-encrypted-password-manager-built-in-java-4nij</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Why SeguraPass Exists&lt;/li&gt;
&lt;li&gt;SeguraPass: The Best of Both Worlds&lt;/li&gt;
&lt;li&gt;Architecture Overview&lt;/li&gt;
&lt;li&gt;Tech Stack&lt;/li&gt;
&lt;li&gt;Application Screenshots&lt;/li&gt;
&lt;li&gt;Challenges Encountered&lt;/li&gt;
&lt;li&gt;Security Considerations&lt;/li&gt;
&lt;li&gt;Installation and Integrity Checks&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Password managers are some of the most sensitive applications we use. They hold the keys to everything: banking accounts, emails, private documents and the entire digital footprint of a person. With such a high level of trust, the traditional architecture of password managers raises an uncomfortable question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why should any company hold your vault, your keys, your password hashes or even metadata about your accounts?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This question defined the foundation of &lt;strong&gt;SeguraPass&lt;/strong&gt;, a free, zero-knowledge, end-to-end encrypted online password manager designed so that your passwords belong only to you. Not the server, not the cloud and not the application developer.&lt;/p&gt;

&lt;p&gt;SeguraPass is a full desktop application built with Java, JavaFX, Spring Boot and PostgreSQL, with cryptographic foundations based on SRP-6a, AES-256-GCM and Argon2id. Its primary objective is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Even in the worst-case scenarios, such as server compromise, credential leaks and insider attacks, no attacker or administrator should be able to derive a single byte of your secrets.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below is a breakdown of why SeguraPass exists, the problems it solves and the architecture behind it.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Why SeguraPass exists
&lt;/h2&gt;

&lt;p&gt;The current ecosystem of password managers largely falls into two camps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cloud-First Password Managers
&lt;/h3&gt;

&lt;p&gt;These are the most mainstream options, as they are convenient, cross-platform and full of syncing features.&lt;/p&gt;

&lt;p&gt;But they come with major security drawbacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They often receive your vault unencrypted and encrypt it on the server.&lt;/li&gt;
&lt;li&gt;They frequently send telemetry or usage analytics.&lt;/li&gt;
&lt;li&gt;They rely on storing hashes of master passwords for login.&lt;/li&gt;
&lt;li&gt;Many still use outdated KDFs.&lt;/li&gt;
&lt;li&gt;Security mostly depends on policy ("We promise we won’t access your data") rather than design.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even when implemented well, these systems require extensive trust:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trust in the company’s servers&lt;/li&gt;
&lt;li&gt;Trust in their cryptographic implementation&lt;/li&gt;
&lt;li&gt;Trust they won’t add a backdoor&lt;/li&gt;
&lt;li&gt;Trust they won’t leak telemetry&lt;/li&gt;
&lt;li&gt;Trust their hashes won’t eventually be cracked&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;History has shown that trust-based systems inevitably fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Local-Only Password Managers
&lt;/h3&gt;

&lt;p&gt;These avoid cloud risk altogether, but introduce a different set of problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No automatic syncing&lt;/li&gt;
&lt;li&gt;Manual data transfer between devices&lt;/li&gt;
&lt;li&gt;No redundancy&lt;/li&gt;
&lt;li&gt;High risk of losing or corrupting local vaults&lt;/li&gt;
&lt;li&gt;No multi-device access&lt;/li&gt;
&lt;li&gt;Poor portable backups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users are thus forced to choose between:&lt;br&gt;
&lt;strong&gt;Convenience and insecurity&lt;/strong&gt;&lt;br&gt;
or&lt;br&gt;
&lt;strong&gt;Security and inconvenience&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SeguraPass was built to combine the best of both worlds and break out of this compromise.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  SeguraPass: The Best of Both Worlds
&lt;/h2&gt;

&lt;p&gt;SeguraPass is built on two fundamental principles:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Zero-Knowledge Authentication
&lt;/h3&gt;

&lt;p&gt;The master password never leaves the device.&lt;br&gt;
The server only stores a verifier generated through SRP-6a, from which attackers cannot reverse-engineer the master password.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Client-Side End-to-End Encryption
&lt;/h3&gt;

&lt;p&gt;Credentials are encrypted before leaving the device using AES-256-GCM and are only ever decrypted locally.&lt;br&gt;
The server never sees plaintext credentials, master passwords, encrypted key material or key derivatives.&lt;/p&gt;

&lt;p&gt;This means that even if the entire database becomes public, &lt;strong&gt;your passwords remain unreadable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;SeguraPass executes four critical workflows that must remain secure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Registering a new user&lt;/li&gt;
&lt;li&gt;Logging in&lt;/li&gt;
&lt;li&gt;Writing credentials&lt;/li&gt;
&lt;li&gt;Reading credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Underlying everything are two SRP parameters (&lt;strong&gt;N&lt;/strong&gt; and &lt;strong&gt;g&lt;/strong&gt;) defined by the RFC5054 3072-bit group.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Registration Flow (SRP-6a)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mr2fb3xy8v67wsxxi3j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mr2fb3xy8v67wsxxi3j.png" alt="Registration flow" width="712" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a new user registers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. The user enters their email and master password.&lt;/li&gt;
&lt;li&gt;2. The client generates:

&lt;ul&gt;
&lt;li&gt;A random authorization salt (for SRP)&lt;/li&gt;
&lt;li&gt;A random key salt (for AES key derivation)&lt;/li&gt;
&lt;li&gt;A verifier &lt;strong&gt;v = g^x mod N&lt;/strong&gt;, where &lt;strong&gt;x = H(saltAuth | masterPassword)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A random device ID&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;3. The client sends only:

&lt;ul&gt;
&lt;li&gt;The randomly generated authorization salt&lt;/li&gt;
&lt;li&gt;The randomly generated key salt&lt;/li&gt;
&lt;li&gt;The verifier v&lt;/li&gt;
&lt;li&gt;The device ID&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;4. The master password never touches the server&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;To activate the newly created account, the user verifies their email address through a link received via email.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Login Flow (SRP-6a Mutual Authentication)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm26u2fxdgx3fkjetcgnj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm26u2fxdgx3fkjetcgnj.png" alt="Login flow" width="622" height="861"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SRP is used again during login:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. Client sends their email, device ID and &lt;strong&gt;A = g^a mod N&lt;/strong&gt;, where &lt;strong&gt;a&lt;/strong&gt; is a randomly generated client secret which cannot be reverse-engineered from &lt;strong&gt;A&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;2. Server responds with &lt;strong&gt;B = (k*v + g^b) mod N&lt;/strong&gt;, where &lt;strong&gt;b&lt;/strong&gt; is a randomly generated server secret which cannot be reverse-engineered from &lt;strong&gt;B&lt;/strong&gt;, &lt;strong&gt;k = H(pad(N) || pad(g))&lt;/strong&gt; and &lt;strong&gt;v&lt;/strong&gt; is the stored SRP verifier. It also sends the stored authorization salt back to the client&lt;/li&gt;
&lt;li&gt;3. Client computes a proof M1, which is calculated like this:

&lt;ul&gt;
&lt;li&gt;First, the premaster secret &lt;strong&gt;S = (B - (k*g)^x)^(a+u*x) mod N&lt;/strong&gt; is calculated, where &lt;strong&gt;u&lt;/strong&gt; is an ephemeral value calculated using &lt;strong&gt;N, A&lt;/strong&gt; and &lt;strong&gt;B&lt;/strong&gt;, meaning both client and server can calculate it independently&lt;/li&gt;
&lt;li&gt;Afterwards, the proof &lt;strong&gt;M1 = H(pad(A) || pad(B) || pad(S))&lt;/strong&gt; is calculated and sent to the server&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;4. Server independently computes M1, calculated like this:

&lt;ul&gt;
&lt;li&gt;Server calculates its own premaster secret &lt;strong&gt;S = (A * v^u)^b mod N&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The server calculates M1 in the same way as the client &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;5. If both M1 proofs match, server sends:

&lt;ul&gt;
&lt;li&gt;A short-lived JWT&lt;/li&gt;
&lt;li&gt;A refresh token that is hashed and stored connected to the client's session&lt;/li&gt;
&lt;li&gt;Its own proof &lt;strong&gt;M2 = H(pad(A) || pad(M1) || pad(S))&lt;/strong&gt;, proving to the client that it independently calculated the same S&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;6. Client calculates own M2 in the same way and verifies server's M2 to ensure the server is legitimate before accessing the service using the supplied tokens&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;If anything has been tampered with, the authentication will fail.&lt;/p&gt;

&lt;p&gt;This creates a fully authenticated session without ever revealing the master password.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Writing Credentials (Client-Side Encryption)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1wi0svrsi2zvxt6acz6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1wi0svrsi2zvxt6acz6.png" alt="Writing credentials" width="606" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before any credentials are stored:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. The client derives a 256-bit AES key using:

&lt;ul&gt;
&lt;li&gt;Argon2id&lt;/li&gt;
&lt;li&gt;The user's master password&lt;/li&gt;
&lt;li&gt;The user's key salt&lt;/li&gt;
&lt;li&gt;Argon2id parameters: 64 MB memory, 3 iterations, 1 lane&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;2. For each credential field (namely website, username and password), a new random 12-byte IV is generated&lt;/li&gt;

&lt;li&gt;3. The client encrypts each field using AES-256-GCM and sends the encrypted fields and their IVs to the server&lt;/li&gt;

&lt;li&gt;4. The server thus only stores field ciphertexts and their IVs, from which field plaintexts cannot be reverse-engineered&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Neither the AES key nor any of its derivatives ever leave the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Reading Credentials
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgp73xu122275mjs5e4ch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgp73xu122275mjs5e4ch.png" alt="Read credentials" width="661" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To read credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. The client fetches encrypted data and IVs&lt;/li&gt;
&lt;li&gt;2. The same Argon2 key is recomputed locally&lt;/li&gt;
&lt;li&gt;3. Credentials are decrypted locally on the device&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At no point does the server have the decryption key or any means to derive it and decrypt the ciphertexts remotely.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Client
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Java 17&lt;/li&gt;
&lt;li&gt;JavaFX 21&lt;/li&gt;
&lt;li&gt;ControlsFX, ValidatorFX&lt;/li&gt;
&lt;li&gt;BootstrapFX + Ikonli&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Server
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Java + Spring Boot&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Cloudflare Tunnel for secure HTTPS access&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Crypto
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SRP-6a (via BouncyCastle)&lt;/li&gt;
&lt;li&gt;AES-256-GCM&lt;/li&gt;
&lt;li&gt;Argon2id&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Packaging &amp;amp; Deployment
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;jlink + jpackage&lt;/li&gt;
&lt;li&gt;Inno Setup installer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Application Screenshots
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Registration screen
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwoxbqi30j7dt7xk7oslm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwoxbqi30j7dt7xk7oslm.png" alt="Registration screen" width="760" height="775"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Login screen
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7li7pzj3yue02rl4dfyo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7li7pzj3yue02rl4dfyo.png" alt="Login screen" width="744" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dashboard
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk86nlzpk1wyciprjrh4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk86nlzpk1wyciprjrh4a.png" alt="Dashboard" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding new credentials
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pmj5r62o0oyvwaqf4v4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pmj5r62o0oyvwaqf4v4.png" alt="Adding new credentials" width="493" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dashboard after new credentials have been added
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fup1swq6x3cibynfftbum.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fup1swq6x3cibynfftbum.png" alt="Dashboard after new credentials have been added" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating existing credentials
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F760ikukaedjxzfwn08o7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F760ikukaedjxzfwn08o7.png" alt="Updating existing credentials" width="493" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deleting existing credentials
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnz0gck23ngbsddx8jdfq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnz0gck23ngbsddx8jdfq.png" alt="Deleting existing credentials" width="365" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges Encountered
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Implementing SRP-6a Correctly
&lt;/h3&gt;

&lt;p&gt;A custom RSA-based scheme was initially considered, with encrypted private keys and challenge signatures. However, it was rejected due to the possibility of offline attacks.&lt;/p&gt;

&lt;p&gt;SRP-6a eliminated this risk and provided a proven, secure, mutual-authentication mechanism.&lt;/p&gt;

&lt;p&gt;Implementing SRP securely required careful handling of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Big integers&lt;/li&gt;
&lt;li&gt;Hashing&lt;/li&gt;
&lt;li&gt;Handling ephemeral values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Storing ephemeral values very briefly (&amp;lt;1 minute) in the DB solved multi-step request flows safely.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Achieving True End-to-End Encryption
&lt;/h3&gt;

&lt;p&gt;Ensuring the server never saw plaintext required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Per-user salts&lt;/li&gt;
&lt;li&gt;On-device Argon2 key derivation&lt;/li&gt;
&lt;li&gt;Random IVs for each field&lt;/li&gt;
&lt;li&gt;Local AES-256-GCM encryption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After implementing this, no plaintext credential data leaves the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Packaging &amp;amp; Distribution
&lt;/h3&gt;

&lt;p&gt;Creating a self-contained Windows installer required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using jlink to produce a custom runtime&lt;/li&gt;
&lt;li&gt;Packaging with jpackage&lt;/li&gt;
&lt;li&gt;Wrapping the output with Inno Setup&lt;/li&gt;
&lt;li&gt;Fixing module issues and JavaFX rendering errors&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Update Handling
&lt;/h3&gt;

&lt;p&gt;A simple, robust update system was implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client checks a version endpoint at startup&lt;/li&gt;
&lt;li&gt;Endpoint returns version, release date and download URL&lt;/li&gt;
&lt;li&gt;If client app is outdated, user must update it to continue&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Secure Client–Server Communication
&lt;/h3&gt;

&lt;p&gt;Even though SRP combined with end-to-end encryption already protects against MITM attacks, HTTPS was still mandatory.&lt;/p&gt;

&lt;p&gt;Cloudflare Tunnel was selected because it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides automatic TLS&lt;/li&gt;
&lt;li&gt;Hides the server’s IP&lt;/li&gt;
&lt;li&gt;Blocks direct inbound traffic&lt;/li&gt;
&lt;li&gt;Reduces malicious traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;p&gt;SeguraPass follows a defense-in-depth model:&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SRP prevents offline attacks and password disclosure&lt;/li&gt;
&lt;li&gt;No password hashes are stored&lt;/li&gt;
&lt;li&gt;All SRP values are strictly validated&lt;/li&gt;
&lt;li&gt;Only BouncyCastle primitives are used&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  End-to-End Encryption
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AES-256-GCM with per-field IVs&lt;/li&gt;
&lt;li&gt;Argon2id with large memory usage&lt;/li&gt;
&lt;li&gt;Zero-knowledge server storage&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Transport Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;TLS enforced via Cloudflare&lt;/li&gt;
&lt;li&gt;Server identity validated through SRP M2&lt;/li&gt;
&lt;li&gt;JWTs validated and short-lived&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Update Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Version endpoint served over HTTPS&lt;/li&gt;
&lt;li&gt;Installer auto-removes old versions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Design Principles
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Secure-by-design, not secure-by-policy&lt;/li&gt;
&lt;li&gt;Strict separation of concerns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Installation and Integrity Checks
&lt;/h2&gt;

&lt;p&gt;Users can simply download the installer EXE or ZIP by going to the following &lt;a href="https://github.com/bartol00/segurapass/tree/main" rel="noopener noreferrer"&gt;link&lt;/a&gt;. Before installation, they can verify integrity via SHA-256 also present at the supplied location.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;SeguraPass was built with one goal in mind:&lt;br&gt;
&lt;strong&gt;Maximum security with zero trust&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By combining modern cryptography, a zero-knowledge design, strong key derivation and secure mutual authentication, SeguraPass eliminates the historical weaknesses of both cloud and local password managers.&lt;/p&gt;

&lt;p&gt;Whether attackers gain full database access, intercept traffic or compromise the infrastructure, they gain nothing but encrypted blobs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your secrets stay yours.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;If you have any questions or suggestions, feel free to leave them in the comments below!&lt;/p&gt;

</description>
      <category>java</category>
      <category>showdev</category>
      <category>security</category>
      <category>saas</category>
    </item>
  </channel>
</rss>
