O Tym Tutorialu
PHP jest doskonałym językiem serwerowym do implementacji algorytmów szyfrowania i budowania bezpiecznych systemów backendowych. Ten kompleksowy tutorial przeprowadzi Cię przez implementację szyfru Cezara w PHP, od podstawowych funkcji po integrację z Laravel i endpointy RESTful API. Niezależnie od tego, czy tworzysz narzędzia edukacyjne, czy uczysz się koncepcji kryptograficznych w kontekście backendu, ten przewodnik pokrywa wszystko, czego potrzebujesz. Przed zanurzeniem się w kod, zapoznaj się z naszym Przewodnikiem dla Początkujących po Szyfrze Cezara, aby zrozumieć podstawy szyfrowania.
Zrozumienie Podstaw
Szyfr Cezara przesuwa każdą literę w tekście jawnym o stałą liczbę pozycji w alfabecie. W PHP użyjemy funkcji ord() i chr() wraz z arytmetyką modularną, aby zaimplementować to efektywnie dla aplikacji serwerowych i API.
Przykład:
Przy przesunięciu o 3, "HELLO" staje się "KHOOR"
Podstawowa Implementacja PHP
Zacznijmy od prostej funkcji szyfrującej, która demonstruje główną koncepcję:
<?php
/**
* Szyfruje tekst używając szyfru Cezara z podaną wartością przesunięcia.
*
* @param string $text Tekst do zaszyfrowania
* @param int $shift Liczba pozycji do przesunięcia (1-25)
* @return string Zaszyfrowany tekst
*/
function caesarEncrypt(string $text, int $shift): string
{
$result = '';
$textLength = strlen($text);
for ($i = 0; $i < $textLength; $i++) {
$char = $text[$i];
// Sprawdź czy znak jest wielką literą
if ($char >= 'A' && $char <= 'Z') {
// Przesuń w obrębie wielkich liter (A-Z)
$code = ord($char);
$char = chr((($code - 65 + $shift) % 26) + 65);
}
// Sprawdź czy znak jest małą literą
elseif ($char >= 'a' && $char <= 'z') {
// Przesuń w obrębie małych liter (a-z)
$code = ord($char);
$char = chr((($code - 97 + $shift) % 26) + 97);
}
// Zachowaj znaki niealfabetyczne bez zmian
$result .= $char;
}
return $result;
}
// Przykład użycia
$plaintext = "Hello World!";
$shift = 3;
$encrypted = caesarEncrypt($plaintext, $shift);
echo "Oryginalny: $plaintext\n";
echo "Zaszyfrowany: $encrypted\n";
// Wyjście:
// Oryginalny: Hello World!
// Zaszyfrowany: Khoor Zruog!
Jak Działa Implementacja PHP
Zrozumienie kluczowych funkcji PHP używanych w szyfrze Cezara:
Funkcja ord()
Zwraca wartość ASCII znaku. Dla 'A', ord('A')
zwraca 65. Jest to niezbędne do konwersji liter na liczby dla operacji matematycznych.
Funkcja chr()
Konwertuje wartości ASCII z powrotem na znaki. chr(65)
zwraca 'A'. Używana do odbudowania zaszyfrowanego ciągu po przesunięciu.
Arytmetyka Modulo (% 26)
Operator modulo owija litery wokół alfabetu. Gdy 'Z' + 1 przekracza alfabet, wraca do 'A'. Kluczowe dla zachowania granic alfabetycznych.
Funkcje Stringowe
str_split()
, strlen()
i konkatenacja stringów umożliwiają efektywne przetwarzanie tekstu. Nowoczesne PHP wspiera również funkcje mb_*
dla Unicode.
Nowoczesna Implementacja PHP 8+
Wykorzystanie nowoczesnych funkcji PHP, w tym deklaracji typów, nazwanych argumentów i wyrażeń match:
<?php
declare(strict_types=1);
/**
* Nowoczesna implementacja szyfru Cezara w PHP 8+
*/
function caesarCipher(string $text, int $shift): string
{
$shift = (($shift % 26) + 26) % 26; // Normalizacja przesunięcia
return implode('', array_map(
fn($char) => match(true) {
ctype_upper($char) => chr(((ord($char) - 65 + $shift) % 26) + 65),
ctype_lower($char) => chr(((ord($char) - 97 + $shift) % 26) + 97),
default => $char
},
str_split($text)
));
}
function caesarDecrypt(string $text, int $shift): string
{
return caesarCipher($text, -$shift);
}
// Przykład użycia z nowoczesnymi funkcjami
$message = "PHP jest potężny w rozwoju backendu!";
$encrypted = caesarCipher($message, 7);
$decrypted = caesarDecrypt($encrypted, 7);
echo "Oryginalny: $message\n";
echo "Zaszyfrowany: $encrypted\n";
echo "Odszyfrowany: $decrypted\n";
Integracja z Laravel
Stwórz klasę serwisu Laravel dla operacji szyfru Cezara z dependency injection i odpowiednią obsługą błędów:
<?php
namespace App\Services;
/**
* Serwis Szyfru Cezara dla aplikacji Laravel
*/
class CaesarCipherService
{
private int $shift;
public function __construct(int $shift = 3)
{
$this->setShift($shift);
}
/**
* Szyfruje tekst używając szyfru Cezara
*/
public function encrypt(string $text): string
{
return $this->transform($text, $this->shift);
}
/**
* Deszyfruje tekst używając szyfru Cezara
*/
public function decrypt(string $text): string
{
return $this->transform($text, -$this->shift);
}
/**
* Przekształca tekst z podanym przesunięciem
*/
private function transform(string $text, int $shift): string
{
$result = '';
$shift = (($shift % 26) + 26) % 26;
foreach (str_split($text) as $char) {
if (ctype_upper($char)) {
$result .= chr(((ord($char) - 65 + $shift) % 26) + 65);
} elseif (ctype_lower($char)) {
$result .= chr(((ord($char) - 97 + $shift) % 26) + 97);
} else {
$result .= $char;
}
}
return $result;
}
/**
* Ustawia nową wartość przesunięcia
*/
public function setShift(int $shift): self
{
if ($shift < 0 || $shift > 25) {
throw new \InvalidArgumentException(
'Przesunięcie musi być między 0 a 25'
);
}
$this->shift = $shift;
return $this;
}
/**
* Pobiera aktualną wartość przesunięcia
*/
public function getShift(): int
{
return $this->shift;
}
}
Budowanie Endpointu RESTful API
Utwórz kontroler API Laravel, aby udostępnić funkcjonalność szyfru Cezara przez endpointy HTTP:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Services\CaesarCipherService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class CaesarCipherController extends Controller
{
public function __construct(
private CaesarCipherService $cipherService
) {}
/**
* Szyfruje tekst używając szyfru Cezara
*
* @param Request $request
* @return JsonResponse
*/
public function encrypt(Request $request): JsonResponse
{
$validator = Validator::make($request->all(), [
'text' => 'required|string|max:10000',
'shift' => 'required|integer|min:1|max:25'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'errors' => $validator->errors()
], 422);
}
try {
$this->cipherService->setShift($request->input('shift'));
$encrypted = $this->cipherService->encrypt(
$request->input('text')
);
return response()->json([
'success' => true,
'data' => [
'original' => $request->input('text'),
'encrypted' => $encrypted,
'shift' => $request->input('shift')
]
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Szyfrowanie nie powiodło się: ' . $e->getMessage()
], 500);
}
}
/**
* Deszyfruje tekst używając szyfru Cezara
*
* @param Request $request
* @return JsonResponse
*/
public function decrypt(Request $request): JsonResponse
{
$validator = Validator::make($request->all(), [
'text' => 'required|string|max:10000',
'shift' => 'required|integer|min:1|max:25'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'errors' => $validator->errors()
], 422);
}
try {
$this->cipherService->setShift($request->input('shift'));
$decrypted = $this->cipherService->decrypt(
$request->input('text')
);
return response()->json([
'success' => true,
'data' => [
'encrypted' => $request->input('text'),
'decrypted' => $decrypted,
'shift' => $request->input('shift')
]
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Deszyfrowanie nie powiodło się: ' . $e->getMessage()
], 500);
}
}
}
// routes/api.php
// Route::post('/caesar/encrypt', [CaesarCipherController::class, 'encrypt']);
// Route::post('/caesar/decrypt', [CaesarCipherController::class, 'decrypt']);
Zaawansowana Implementacja Oparta na Klasach
Dla aplikacji produkcyjnych kompleksowe podejście oparte na klasach zapewnia lepszą organizację, walidację i możliwość wielokrotnego użycia:
<?php
declare(strict_types=1);
/**
* Kompleksowa implementacja Szyfru Cezara z zaawansowanymi funkcjami
*/
class CaesarCipher
{
private int $shift;
private string $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
public function __construct(int $shift = 3)
{
$this->setShift($shift);
}
/**
* Szyfruje tekst
*/
public function encrypt(string $text): string
{
return $this->transform($text, $this->shift);
}
/**
* Deszyfruje tekst
*/
public function decrypt(string $text): string
{
return $this->transform($text, -$this->shift);
}
/**
* Przekształca tekst z podanym przesunięciem
*/
private function transform(string $text, int $shift): string
{
$result = '';
$shift = (($shift % 26) + 26) % 26;
foreach (str_split($text) as $char) {
if (ctype_upper($char)) {
$result .= chr(((ord($char) - 65 + $shift) % 26) + 65);
} elseif (ctype_lower($char)) {
$result .= chr(((ord($char) - 97 + $shift) % 26) + 97);
} else {
$result .= $char;
}
}
return $result;
}
/**
* Atak brute force - wypróbuj wszystkie możliwe przesunięcia
*
* @param string $encryptedText Tekst do odszyfrowania
* @return array Wszystkie 26 możliwych odszyfrowań
*/
public function bruteForce(string $encryptedText): array
{
$results = [];
for ($shift = 0; $shift < 26; $shift++) {
$results[] = [
'shift' => $shift,
'text' => $this->transform($encryptedText, -$shift)
];
}
return $results;
}
/**
* Szyfruje/deszyfruje zawartość pliku
*/
public function processFile(
string $inputFile,
string $outputFile,
bool $encrypt = true
): bool {
if (!file_exists($inputFile)) {
throw new \RuntimeException("Plik wejściowy nie został znaleziony");
}
$content = file_get_contents($inputFile);
$processed = $encrypt
? $this->encrypt($content)
: $this->decrypt($content);
return file_put_contents($outputFile, $processed) !== false;
}
/**
* Ustawia wartość przesunięcia z walidacją
*/
public function setShift(int $shift): self
{
$this->shift = (($shift % 26) + 26) % 26;
return $this;
}
/**
* Pobiera aktualną wartość przesunięcia
*/
public function getShift(): int
{
return $this->shift;
}
/**
* ROT13 - Szyfr Cezara z przesunięciem 13
*/
public static function rot13(string $text): string
{
return (new self(13))->encrypt($text);
}
/**
* Sprawdza czy tekst jest prawdopodobnie zaszyfrowany szyfrem Cezara
*/
public function isLikelyEncrypted(string $text): bool
{
// Prosta heurystyka: sprawdź rozkład częstotliwości liter
$letterCount = preg_match_all('/[a-zA-Z]/', $text);
if ($letterCount === 0) {
return false;
}
// Policz częste polskie litery (A, E, I, O, Z, N)
$commonLetters = preg_match_all('/[aeionzAEIONZ]/', $text);
$ratio = $commonLetters / $letterCount;
// Jeśli współczynnik jest bardzo niski, tekst może być zaszyfrowany
return $ratio < 0.3;
}
}
// Przykład użycia
$cipher = new CaesarCipher(5);
// Szyfrowanie
$message = "PHP jest świetny do rozwoju backendu!";
$encrypted = $cipher->encrypt($message);
echo "Oryginalny: $message\n";
echo "Zaszyfrowany: $encrypted\n";
// Deszyfrowanie
$decrypted = $cipher->decrypt($encrypted);
echo "Odszyfrowany: $decrypted\n";
// Atak brute force
$mysteryText = "Mjqqt Btwqi";
echo "\nWyniki brute force:\n";
foreach (array_slice($cipher->bruteForce($mysteryText), 0, 5) as $result) {
echo "Przesunięcie {$result['shift']}: {$result['text']}\n";
}
// ROT13
$rot13Text = CaesarCipher::rot13("Hello World");
echo "\nROT13: $rot13Text\n";
Najlepsze Praktyki PHP
Nasza implementacja przestrzega nowoczesnych standardów i najlepszych praktyk PHP:
- Deklaracje Typów: Używaj ścisłego typowania z
declare(strict_types=1)
dla większego bezpieczeństwa kodu - Komentarze PHPDoc: Jasna dokumentacja wyjaśniająca parametry, typy zwracane i wyjątki
- Standard Kodowania PSR-12: Przestrzegaj standardów PHP-FIG dla spójnego stylu kodu
- Obsługa Błędów: Używaj wyjątków dla warunków błędu zamiast kodów zwrotnych
- Walidacja Danych Wejściowych: Zawsze waliduj i oczyszczaj dane wejściowe użytkownika, szczególnie w kontekście webowym
- Dependency Injection: Używaj kontenera serwisów Laravel dla lepszej testowalności
Częste Błędy do Uniknięcia
Uważaj na te częste błędy podczas implementacji szyfru Cezara w PHP:
- Problemy z Kodowaniem Znaków: Zawsze używaj kodowania UTF-8 i rozważ funkcje
mb_*
dla znaków międzynarodowych - Zapomnienie o Modulo: Bez % 26, kody znaków mogą przekroczyć poprawny zakres ASCII
- Brak Normalizacji Przesunięcia: Obsługuj prawidłowo ujemne przesunięcia i wartości > 26
- Wielkość Liter: Obsługuj wielkie i małe litery z różnymi wartościami bazowymi (65 dla A, 97 dla a)
- Błędne Wyobrażenia o Bezpieczeństwie: Nigdy nie używaj szyfru Cezara do prawdziwego zabezpieczenia - jest tylko edukacyjny
Interfejs Wiersza Poleceń (CLI)
Skrypty PHP można uruchamiać z wiersza poleceń do przetwarzania wsadowego i automatyzacji:
<?php
// caesar-cli.php - Narzędzie wiersza poleceń dla szyfru Cezara
declare(strict_types=1);
require_once 'CaesarCipher.php';
function displayHelp(): void
{
echo <<<HELP
Narzędzie CLI Szyfru Cezara
Użycie:
php caesar-cli.php [operacja] [tekst] [przesunięcie]
Operacje:
encrypt Szyfruje podany tekst
decrypt Deszyfruje podany tekst
brute Wypróbuj wszystkie przesunięcia (atak brute force)
Przykłady:
php caesar-cli.php encrypt "Hello World" 3
php caesar-cli.php decrypt "Khoor Zruog" 3
php caesar-cli.php brute "Mjqqt Btwqi"
HELP;
}
// Przetwórz argumenty wiersza poleceń
if ($argc < 2) {
displayHelp();
exit(1);
}
$operation = $argv[1] ?? '';
$text = $argv[2] ?? '';
$shift = isset($argv[3]) ? (int)$argv[3] : 3;
try {
$cipher = new CaesarCipher($shift);
switch ($operation) {
case 'encrypt':
if (empty($text)) {
throw new InvalidArgumentException('Tekst jest wymagany');
}
$result = $cipher->encrypt($text);
echo "Zaszyfrowany: $result\n";
break;
case 'decrypt':
if (empty($text)) {
throw new InvalidArgumentException('Tekst jest wymagany');
}
$result = $cipher->decrypt($text);
echo "Odszyfrowany: $result\n";
break;
case 'brute':
if (empty($text)) {
throw new InvalidArgumentException('Tekst jest wymagany');
}
echo "Wyniki brute force:\n";
foreach ($cipher->bruteForce($text) as $result) {
printf(
"Przesunięcie %2d: %s\n",
$result['shift'],
$result['text']
);
}
break;
default:
displayHelp();
exit(1);
}
} catch (Exception $e) {
echo "Błąd: " . $e->getMessage() . "\n";
exit(1);
}
Praktyczne Przypadki Użycia
Implementacje szyfru Cezara w PHP są idealne do:
Rozważania dotyczące Wydajności
Implementacja ma złożoność czasową O(n), gdzie n to długość tekstu. Dla optymalnej wydajności w PHP:
- Używaj
str_split()
i funkcji tablicowych zamiast iteracji znak po znaku - Rozważ cache'owanie zaszyfrowanych alfabetów dla operacji masowych
- Używaj rozszerzenia
mb_string
do obsługi tekstu UTF-8 - Dla dużych plików, przetwarzaj w kawałkach aby zarządzać użyciem pamięci
- Włącz OPcache w produkcji dla cache'owania bytecode'u
- Profiluj z Xdebug lub Blackfire dla możliwości optymalizacji
Testowanie Implementacji
Kompleksowe testy PHPUnit aby zweryfikować, że Twój szyfr Cezara działa poprawnie:
<?php
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
use App\Services\CaesarCipherService;
class CaesarCipherTest extends TestCase
{
private CaesarCipherService $cipher;
protected function setUp(): void
{
$this->cipher = new CaesarCipherService(3);
}
/** @test */
public function it_encrypts_basic_text_correctly()
{
$this->assertEquals('DEF', $this->cipher->encrypt('ABC'));
}
/** @test */
public function it_handles_wrap_around_from_z_to_a()
{
$this->assertEquals('ABC', $this->cipher->encrypt('XYZ'));
}
/** @test */
public function it_preserves_case()
{
$this->assertEquals('Khoor', $this->cipher->encrypt('Hello'));
}
/** @test */
public function it_keeps_non_alphabetic_characters_unchanged()
{
$encrypted = $this->cipher->encrypt('Hello, World!');
$this->assertEquals('Khoor, Zruog!', $encrypted);
}
/** @test */
public function encryption_and_decryption_are_reversible()
{
$original = 'Programowanie PHP';
$encrypted = $this->cipher->encrypt($original);
$decrypted = $this->cipher->decrypt($encrypted);
$this->assertEquals($original, $decrypted);
}
/** @test */
public function it_handles_shift_of_zero()
{
$this->cipher->setShift(0);
$this->assertEquals('Test', $this->cipher->encrypt('Test'));
}
/** @test */
public function it_throws_exception_for_invalid_shift()
{
$this->expectException(\InvalidArgumentException::class);
$this->cipher->setShift(26);
}
/** @test */
public function it_handles_empty_string()
{
$this->assertEquals('', $this->cipher->encrypt(''));
}
/** @test */
public function it_handles_long_text()
{
$longText = str_repeat('ABC ', 1000);
$encrypted = $this->cipher->encrypt($longText);
$decrypted = $this->cipher->decrypt($encrypted);
$this->assertEquals($longText, $decrypted);
}
}
Pomysły na Rozszerzenia
Rozszerz tę implementację o dodatkowe funkcje:
Powiązane Zasoby
Kontynuuj swoją naukę kryptografii i PHP:
- Wypróbuj nasze interaktywne Narzędzie Szyfru Cezara
- Poznaj bardziej bezpieczny Szyfr Vigenère'a
- Odkryj ROT13, specjalny przypadek z przesunięciem 13
- Poznaj techniki Łamania Szyfru Cezara
- Zobacz implementacje w JavaScript, Pythonie, Javie i C
Podsumowanie
Nauczyłeś się implementować szyfr Cezara w PHP od podstawowych funkcji po integrację z Laravel i RESTful API. Omówiliśmy klasyczne implementacje, nowoczesną składnię PHP 8+, klasy serwisów, endpointy API i narzędzia wiersza poleceń. Ta wiedza stanowi podstawę do budowania bardziej zaawansowanych narzędzi szyfrujących po stronie serwera i zrozumienia kryptografii backendowej.
Ćwicz tworząc własny serwis Laravel, zbuduj kompletne API z autentykacją lub eksperymentuj z bardziej złożonymi algorytmami szyfrowania. Choć szyfr Cezara nie nadaje się do zabezpieczania wrażliwych danych, stanowi doskonałe wprowadzenie do koncepcji kryptograficznych i manipulacji stringów w PHP dla programistów backendowych.