← Back to context

Comment by alright2565

5 days ago

If you are needing to version your password hashes, then you are likely doing them incorrectly and not using a proper computationally-hard hashing algorithm.

For example, with unsuitable algorithms like sha256, you get this, which doesn't have a version field:

    import hashlib; print(f"MD5:      {hashlib.md5(b'password').hexdigest()}")
    print(f"SHA-256:  {hashlib.sha256(b'password').hexdigest()}")


    MD5:      5f4dcc3b5aa765d61d8327deb882cf99
    SHA-256:  5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

But if you use a proper password hash, then your hashing library will automatically take care of versioning your hash, and you can just treat it as an opaque blob:

    import argon2; print(f"Argon2:   {argon2.PasswordHasher().hash('password')}")
    import bcrypt; print(f"bcrypt:   {bcrypt.hashpw(b'password', bcrypt.gensalt()).decode()}")
    from passlib.hash import scrypt; print(f"scrypt:   {scrypt.hash('password')}")


    Argon2:   $argon2id$v=19$m=65536,t=3,p=4$LZ/H9PWV2UV3YTgF3Ixrig$aXEtfkmdCMXX46a0ZiE0XjKABfJSgCHA4HmtlJzautU
    bcrypt:   $2b$12$xqsibRw1wikgk9qhce0CGO9G7k7j2nfpxCmmasmUoGX4Rt0B5umuG
    scrypt:   $scrypt$ln=16,r=8,p=1$/V8rpRTCmDOGcA5hjPFeCw$6N1e9QmxuwqbPJb4NjpGib5FxxILGoXmUX90lCXKXD4

This isn't a new thing, and as far as I'm aware, it's derived from the old apache htpasswd format (although no one else uses the leading colon)

    $ htpasswd -bnBC 10 "" password
    :$2y$10$Bh67PQAd4rqAkbFraTKZ/egfHdN392tyQ3I1U6VnjZhLoQLD3YzRe

Also worth noting, you sometimes come into an existing system that has no hashing, or weak hashing (md5) and nothing with versioning to begin with... if you establish your own prefix v#. you can check for it against existing entries, then add your versioning prefix... even if you move to something that already embeds its' details.

It's not a leading colon: It is a colon separator between the username and password, and the command used has the username as an empty string.