You are browsing as a guest. Sign up (or log in) to start making projects!

4h 44m logged

Determinist // Devlog 10 // 2026.08.27

Updates here and there, and the v3 algorithm is finally complete! All of this and the content of the rest of the devlogs will only be released with the final 1.0.0 release of Determinist.

Changes

  • Added v3 algorithm for the Python CLI
    • It features dynamic byte generation so that no matter what, you’ll never run out of characters! (Unless you’re VERY unlucky)
    • You can now enter a third value called a “differentiator” that can be used to change the output further. This is especially useful if you have multiple accounts on the same site. This option can be left empty
    • Your generated password is now guaranteed to have the correct amount of characters
    • You can now set a minimum amount of characters of each type! Simply enter 0 to exclude the character type, and 1 or above to choose how many characters your password have minimum of that type.
  • Made generate prompt only prompt users if the prompts are applicable. This means you will no longer be prompted for the settings of v1 when you use one of the other two algorithms.
  • Fixed an issue where if the site_name option is omitted, the prompt will display Master pass instead of the correct prompt.

The difficulties

Well, of course the development of v3 came with some challenges. Firstly, I had to figure out how to actually generate enough bytes to pass rejection sampling (making sure no bytes are out of range when mapped onto the character set), as the previous implementation was that I multiplied the password length by 32. This worked, but wasn’t pretty and in very rare and unlucky cases, there weren’t enough bytes. I fixed this by using something called HKDF, which stands for HMAC-based Extract-and-Expand Key Derivation Function. I’d really prefer to use HKDF. Anyway, this function was really good for this task, as it can take the Argon2 output and create a long, pseudo-random key that can go through rejection sampling, and finally end up in the password. In case this generated key is not enough, HKDF will generate more of it, essentially giving us infinite bytes to then map to our characters. This was especially good because in the same loop I could implement…

Minimum requirements

This should have been easy, but it took me a day to think about how to do it. The challenge: take a dictionary ({"lowercase": 2, "uppercase": 3, "special": 1, "digits": 0}), and include at least as many characters of each type as their value in that dictionary says, and if it’s 0 then don’t include it at all. Fine, I said, but I didn’t actually know how to implement this. After a day of thinking, it finally clicked: I implement this in the rejection sampling loop, as that is where my characters get added. Introducing the _construct_pass function: it looks for the already added characters, determines the type of the current character, counts how many are missing, and if a character type is missing some characters or there aren’t any left, the character is added, and otherwise it is discarded.

To do

  • Add a preset generator command
  • Fix a g prefix appearing in the version command output before the git commit hash
  • Add the ability to choose a preset in one line instead of being prompted for it
  • Fix the password being allowed to be shorter than the sum of minimum required characters (I found that one while writing this)
  • Port everything over to the website
  • Update the docs
  • Add more text to the website explaining Determinist and how it works
1
153

Comments 0

No comments yet. Be the first!