Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpass Laravel Package

bordoni/phpass

Modernized, namespaced fork of Openwall Phpass (0.3) with Composer autoloading and unit tests. Provides PasswordHash for hashing and verifying passwords with minimal stylistic changes; public domain code, PHP 5 style.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal steps, where to look first, first use case

  1. Installation:

    composer require bordoni/phpass
    

    Add to composer.json under "require":

    "bordoni/phpass": "^0.3.6"
    
  2. First Use Case: Hash and verify a password in a Laravel controller:

    use Hautelook\Phpass\PasswordHash;
    
    // Initialize with cost factor (8-31) and portability mode
    $hasher = new PasswordHash(8, false);
    
    // Hash a password (e.g., during registration)
    $hash = $hasher->HashPassword('user_provided_password');
    
    // Verify a password (e.g., during login)
    $isValid = $hasher->CheckPassword('user_input_password', $stored_hash_from_db);
    
  3. Where to Look First:

    • README.md for basic usage patterns.
    • Openwall Phpass docs for algorithmic details.
    • src/PasswordHash.php for method signatures, edge cases, and internal logic.

Implementation Patterns

Usage patterns, workflows, integration tips

Core Workflows

  1. Registration Flow:

    // In a Laravel controller or service
    $hasher = resolve(PasswordHash::class); // If bound in service provider
    $hash = $hasher->HashPassword(request('password'));
    
    User::create([
        'email' => request('email'),
        'password' => $hash,
    ]);
    
  2. Login Flow:

    $user = User::where('email', request('email'))->first();
    if ($user && $hasher->CheckPassword(request('password'), $user->password)) {
        // Authenticate user
    }
    
  3. Password Reset:

    // Generate a token, store it, then reset:
    $hasher->HashPassword(request('new_password')) // New hash for DB
    

Laravel Integration Patterns

  1. Service Provider Binding:

    // app/Providers/AppServiceProvider.php
    public function register()
    {
        $this->app->bind(PasswordHash::class, function ($app) {
            return new PasswordHash(
                config('auth.password.cost', 8),
                config('auth.password.portable', false)
            );
        });
    }
    

    Configure in config/auth.php:

    'password' => [
        'cost' => 10, // Default cost factor
        'portable' => false, // Enable only for legacy systems
    ],
    
  2. Form Request Validation:

    use Illuminate\Validation\Rule;
    
    public function rules()
    {
        return [
            'password' => [
                'required',
                'string',
                'min:8',
                Rule::unique('users')->ignore($this->user),
            ],
        ];
    }
    
  3. Testing:

    // Mock PasswordHash in unit tests
    $mock = Mockery::mock(PasswordHash::class);
    $mock->shouldReceive('HashPassword')
         ->with('test_password')
         ->andReturn('$2a$08$hashed_value');
    $this->app->instance(PasswordHash::class, $mock);
    

Database Considerations

  • Schema Migration:
    Schema::table('users', function (Blueprint $table) {
        $table->string('password')->nullable()->change();
    });
    
  • Backfilling: Use a seeder to rehash existing passwords:
    $users = User::all();
    $newHasher = new PasswordHash(10, false);
    
    foreach ($users as $user) {
        $oldHasher = new PasswordHash(4, true); // Match old cost
        $hash = $newHasher->HashPassword($user->password);
        $user->update(['password' => $hash]);
    }
    

Gotchas and Tips

Pitfalls, debugging, config quirks, extension points

Common Pitfalls

  1. Cost Factor Misconfiguration:

    • Issue: Setting cost too low (e.g., <8) weakens security; too high (e.g., >12) causes performance bottlenecks.
    • Fix: Default to 8 or 10 for most applications. Benchmark under load.
  2. Portability Mode:

    • Issue: Enabling portable_hashes=true reduces security by supporting older hash formats.
    • Fix: Only enable if migrating from a legacy system. Document the tradeoff.
  3. PHP Version Incompatibilities:

    • Issue: PHP 8.1+ may trigger deprecation warnings (fixed in 0.3.6).
    • Fix: Pin to ^0.3.6:
      composer require bordoni/phpass:^0.3.6
      
  4. Hash Format Assumptions:

    • Issue: Phpass hashes always start with $2a$. Mixing with Laravel’s native bcrypt (e.g., $2y$) will fail.
    • Fix: Stick to one hashing system per application.
  5. Database Truncation:

    • Issue: Storing hashes in a varchar(60) column may truncate long hashes (unlikely but possible).
    • Fix: Use varchar(255) for safety.

Debugging Tips

  1. Failed Verification:

    • Symptom: CheckPassword returns false for correct credentials.
    • Debug Steps:
      • Verify the stored hash isn’t truncated or corrupted in the database.
      • Check for hidden characters (e.g., \n, \r) in the input password.
      • Log the raw hash and input for comparison:
        \Log::debug('Stored hash:', [$user->password]);
        \Log::debug('Input password:', [request('password')]);
        
  2. Performance Issues:

    • Symptom: Slow response during login/registration.
    • Debug Steps:
      • Increase the cost factor incrementally (e.g., from 8 to 10) and test.
      • Monitor server CPU/memory usage under load.
      • Consider caching PasswordHash instance (it’s stateless but instantiation is cheap).
  3. Deprecation Warnings:

    • Symptom: PHP 8.1+ warnings like intval() expects parameter 1 to be int.
    • Fix: Upgrade to 0.3.6 or patch locally:
      // In PasswordHash.php, replace:
      intval($this->iterations)
      // With:
      (int)$this->iterations
      

Extension Points

  1. Dynamic Cost Factor:

    // Adjust cost based on server load or user role
    $cost = config('hash.cost');
    if (app()->environment('production')) {
        $cost = min(12, $cost); // Cap at 12 for production
    }
    $hasher = new PasswordHash($cost, false);
    
  2. Password Strength Enforcement: Combine with Laravel’s validation:

    use Illuminate\Validation\Rules\Password as PasswordRule;
    
    'password' => [
        'required',
        'string',
        new PasswordRule, // Built-in strength rules
        'min:8',
    ],
    
  3. Audit Logging:

    // Log failed attempts
    if (!$hasher->CheckPassword($input, $stored)) {
        event(new FailedLoginAttempt(
            user: $user,
            ip: request()->ip(),
            timestamp: now()
        ));
    }
    
  4. Legacy Hash Migration:

    // Rehash passwords from an old system
    $legacyHasher = new PasswordHash(4, true); // Match old cost
    $newHasher = new PasswordHash(10, false);
    
    User::chunk(100, function ($users) use ($legacyHasher, $newHasher) {
        foreach ($users as $user) {
            // Verify old hash first (optional)
            if ($legacyHasher->CheckPassword('old_password', $user->password)) {
                $user->password = $newHasher->HashPassword('old_password');
                $user->save();
            }
        }
    });
    
  5. Custom Hash Storage:

    // Store additional metadata with the hash
    $hashData = [
        'hash' => $hasher->HashPassword($password),
        'cost' => 8,
        'created_at' => now(),
    ];
    $user->password = json_encode($hashData);
    

Configuration Quirks

  1. Cost Factor Limits:

    • Phpass supports 431. Values outside this range will be clamped.
  2. Portability Mode:

    • When true, Phpass supports older hash formats (e.g., $2y$ from other bcrypt implementations). This may introduce compatibility issues.
  3. **Thread

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky