nimblephp / crypto
Encryption, hashing, signing and secure random utilities for NimblePHP
Requires
- php: >=8.2
- ext-openssl: *
- nimblephp/framework: >=0.4.18
Requires (Dev)
- phpunit/phpunit: ^11.5
README
Pakiet dostarcza szyfrowanie, hashowanie, podpisywanie i bezpieczną losowość dla aplikacji opartych o NimblePHP.
Wymagania
- PHP:
>=8.2 ext-opensslnimblephp/framework:>=0.4.13(wymaga wsparcia dla prefiksówbase64:/hex:/file:/json:/env:wConfig::get())
Co jest rejestrowane przez moduł?
crypto.encryption→NimblePHP\Crypto\Services\EncryptionService(implementujeEncrypterInterface)crypto.hasher→NimblePHP\Crypto\Services\HasherService(implementujeHasherInterface)crypto.signature→NimblePHP\Crypto\Services\SignatureServicecrypto.random→NimblePHP\Crypto\Services\RandomService
oraz statyczna fasada NimblePHP\Crypto\Crypto (wygodny dostęp bez pobierania z kontenera).
Konfiguracja klucza (.env)
Szyfrowanie i podpisywanie używają kluczy wersjonowanych, co pozwala na rotację bez utraty dostępu do wcześniej zaszyfrowanych danych:
ENCRYPTION_KEY_CURRENT=1 ENCRYPTION_KEY_1=base64:AbCdEf1234...
Wygeneruj klucz komendą CLI:
php vendor/bin/nimble crypto:generate-key --write
--write dopisuje nową wersję klucza do .env i podbija ENCRYPTION_KEY_CURRENT. Nigdy nie nadpisuje istniejących wpisów — stare dane pozostają odszyfrowywalne starym kluczem. Bez --write klucz jest tylko wypisywany na ekran.
Rotacja klucza
php vendor/bin/nimble crypto:generate-key --write
Dopisze ENCRYPTION_KEY_2 i ustawi ENCRYPTION_KEY_CURRENT=2. Nowe dane będą szyfrowane kluczem 2, a stare dane (zaszyfrowane kluczem 1) nadal da się odszyfrować — wersja klucza jest zapisana w każdym ciphertext.
Użycie w kodzie
Szyfrowanie (odwracalne, AES-256-GCM)
use NimblePHP\Crypto\Crypto; $ciphertext = Crypto::encrypt('dane wrażliwe'); $plaintext = Crypto::decrypt($ciphertext); // Bezpieczna wersja bez wyjątku - zwraca null zamiast rzucać $plaintext = Crypto::tryDecrypt($ciphertext); // Tablice (JSON w środku) $ciphertext = Crypto::encryptArray(['user_id' => 42]); $data = Crypto::decryptArray($ciphertext);
Dodatkowy sekret kontekstowy (opcjonalnie)
Pozwala związać szyfrowanie z dodatkowym sekretem (np. hasłem użytkownika) - nawet wyciek .env i bazy danych nie wystarczy, żeby odczytać dane bez tego sekretu.
$ciphertext = Crypto::encrypt('prywatna notatka', context: $hasloUzytkownika); $plaintext = Crypto::decrypt($ciphertext, context: $hasloUzytkownika);
Uwaga: bez podania tego samego
contextprzy odszyfrowaniu dane są nieodzyskiwalne - to zamierzone działanie. Jeśli sekret (np. hasło użytkownika) się zmienia, trzeba w tym samym kroku odszyfrować danym starym sekretem i zaszyfrować ponownie nowym, inaczej dane przepadną bezpowrotnie.
Hashowanie (jednokierunkowe, Bcrypt)
$hash = Crypto::hash('haslo-uzytkownika'); $ok = Crypto::verify('haslo-uzytkownika', $hash);
Podpisywanie (HMAC-SHA256)
Dane zostają jawne, ale otrzymują podpis potwierdzający autentyczność i integralność (np. podpisane URL-e, dane webhooków).
$signature = Crypto::sign('user_id=42&expires=1999999999'); $valid = Crypto::verifySignature('user_id=42&expires=1999999999', $signature);
Bezpieczna losowość
$bytes = Crypto::randomBytes(32); $token = Crypto::randomToken(32); // 64-znakowy hex, np. do API key / tokenu resetu hasła
CLI
| Komenda | Opis |
|---|---|
crypto:generate-key [--write] |
Generuje nowy klucz 256-bit; z --write dopisuje go do .env |
crypto:encrypt "tekst" [--context=sekret] |
Szyfruje tekst i wypisuje ciphertext |
crypto:decrypt "ciphertext" [--context=sekret] |
Odszyfrowuje tekst |
crypto:hash "tekst" |
Generuje hash Bcrypt (np. do wklejenia hasła do bazy) |
crypto:sign "tekst" |
Generuje podpis HMAC-SHA256 |
crypto:token [dlugosc] |
Generuje losowy token hex (domyślnie 32 bajty → 64 znaki) |
Rozszerzenie Config::get() (nimblephp/framework)
Ten pakiet korzysta z rozszerzenia Config::get() we Framework, które automatycznie dekoduje wartości .env z prefiksem:
base64:...→base64_decodehex:...→hex2binfile:/sciezka→ zawartość plikujson:{...}→json_decodedo tablicyenv:INNA_ZMIENNA→ odczyt wskazanej zmiennej.env(rekurencyjnie)
Dzięki temu klucz szyfrujący może być trzymany np. w pliku poza repozytorium (ENCRYPTION_KEY_1=file:/run/secrets/app_key) zamiast bezpośrednio w .env.
Współtworzenie
Zachęcamy do współtworzenia! Masz sugestie, znalazłeś błąd albo chcesz dorzucić usprawnienia? Otwórz issue lub prześlij pull request.
Pomoc
Pytania i problemy zgłaszaj przez zakładkę Discussions w repozytorium GitHub tego modułu.