Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 12, 2026

Addresses security vulnerability where passwords were stored using unsalted SHA1 hashes, making them vulnerable to rainbow table attacks and practical offline cracking if the database is compromised.

Implementation

  • Bcrypt hashing: New passwords use Authen::Passphrase::BlowfishCrypt with cost factor 12 and random salts
  • Transparent migration: SHA1 passwords automatically upgrade to bcrypt on successful login
  • Constant-time comparison: Legacy SHA1 verification uses XOR-based byte comparison to prevent timing attacks
  • Data consistency: In-memory password hashes sync with database after change_password()

Key Functions

sub _hash_password {
    my $password = shift;
    die "ERROR: password required for hashing\n" if !defined $password || !length($password);
    
    my $ppr = Authen::Passphrase::BlowfishCrypt->new(
        cost        => 12,
        salt_random => 1,
        passphrase  => $password,
    );
    
    return $ppr->as_rfc2307();
}

sub _verify_password {
    my ($password, $stored_hash) = @_;
    
    # Bcrypt verification
    if ($stored_hash =~ /^\{CRYPT\}/) {
        my $ppr = Authen::Passphrase->from_rfc2307($stored_hash);
        return $ppr->match($password) ? 1 : 0;
    }
    
    # Legacy SHA1 with constant-time comparison
    my $computed_hash = sha1_hex($password);
    my $result = 0;
    my $len_a = length($stored_hash);
    my $len_b = length($computed_hash);
    
    $result |= $len_a ^ $len_b;
    
    for (my $i = 0; $i < ($len_a < $len_b ? $len_b : $len_a); $i++) {
        my $byte_a = $i < $len_a ? ord(substr($stored_hash, $i, 1)) : 0;
        my $byte_b = $i < $len_b ? ord(substr($computed_hash, $i, 1)) : 0;
        $result |= $byte_a ^ $byte_b;
    }
    
    return $result == 0 ? 1 : 0;
}

Backwards Compatibility

All existing SHA1 passwords continue to work. No database migration or user intervention required.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 3 commits January 12, 2026 10:34
- Add Authen::Passphrase and Authen::Passphrase::BlowfishCrypt imports
- Implement _hash_password() using bcrypt with cost factor 12
- Implement _verify_password() supporting both bcrypt and legacy SHA1 hashes
- Implement _needs_password_upgrade() to detect legacy hashes
- Update add_user() to hash new passwords with bcrypt
- Update change_password() to use bcrypt hashing
- Update login() to verify passwords with both hash types and auto-migrate SHA1 to bcrypt on successful login
- Update compare_password() to use new verification function
- Maintains backwards compatibility with existing SHA1 hashed passwords

Co-authored-by: frankiejol <[email protected]>
- Fix password validation to check for defined and non-empty values
- Add constant-time comparison for legacy SHA1 hashes to prevent timing attacks
- Add error handling for password upgrade during login (logs warning but doesn't break login)
- Update in-memory password hash after change_password to maintain consistency

Co-authored-by: frankiejol <[email protected]>
- Replace bitwise AND comparison with XOR-based constant-time comparison to prevent timing leaks
- Always compare full byte sequences regardless of length differences
- Sanitize error messages in password upgrade logging to avoid exposing sensitive information

Co-authored-by: frankiejol <[email protected]>
Copy link
Contributor Author

Copilot AI commented Jan 12, 2026

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • esm.ubuntu.com
    • Triggering command: /usr/lib/apt/methods/https /usr/lib/apt/methods/https (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title [WIP] WIP address feedback on user status refresh after password change Replace insecure SHA1 password hashing with bcrypt Jan 12, 2026
Copilot AI requested a review from frankiejol January 12, 2026 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants