Files
ADconsle/app/Services/AttributeCipher.php
T
kzbkowskiandClaude Sonnet 5 1126d96271
CI / PHP 8.2 (push) Failing after 2m46s
CI / PHP 8.3 (push) Failing after 59s
CI / PHP 8.4 (push) Failing after 1m7s
ADconsole v1.0.0
First public release.

- docs: document the audit log, user offboarding, CSV export and the
  "require a reason for destructive actions" setting across README, docs/
  and CLAUDE/AGENTS.md; note retention for panel_audit
- docs: fill the publishing placeholders (repo URL, security contact,
  issue-template links) and add a semantic-versioning policy
- move agent/contributor context into CLAUDE/ (AGENTS.md + a README);
  root CLAUDE.md is now a thin @-import pointer
- add a favicon (shield-lock, matching the login screen) to the login
  page and the app layout
- CHANGELOG: promote [Unreleased] to [1.0.0]; keep the earlier internal
  build as [0.1.0]

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UfuvfwexztdS7LDpGuKsuK
2026-09-08 23:14:39 +02:00

95 lines
2.8 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Encryption\Encrypter;
/**
* Szyfrowanie / odszyfrowanie wartości atrybutów oznaczonych w konfiguracji
* panelu jako "szyfrowany" (np. msDS-cloudExtensionAttribute1/2).
*
* Format szyfrogramu jest zgodny z Laravel Crypt (AES-CBC + MAC), dzięki
* czemu panel odczyta wartości zaszyfrowane wcześniej wartością APP_KEY.
* Klucz z konfiguracji panelu:
* - "base64:...." dekodujące się do 16 lub 32 bajtów -> użyty wprost
* (tu wklej wartość APP_KEY, jeśli atrybuty były nią szyfrowane),
* - dowolny inny tekst (hasło) -> klucz = SHA-256 z tego tekstu (32 B).
* Puste = szyfrowanie wyłączone (wartości przechodzą bez zmian).
*/
class AttributeCipher
{
protected ?Encrypter $encrypter = null;
public function __construct(protected PanelSettingsService $settings) {}
public function isConfigured(): bool
{
return $this->settings->encryptionKey() !== '';
}
protected function keyBytes(): string
{
$key = $this->settings->encryptionKey();
if (str_starts_with($key, 'base64:')) {
$decoded = base64_decode(substr($key, 7), true);
if ($decoded !== false && in_array(strlen($decoded), [16, 32], true)) {
return $decoded;
}
}
return hash('sha256', $key, true); // 32 bajty
}
protected function encrypter(): Encrypter
{
if ($this->encrypter === null) {
$key = $this->keyBytes();
$this->encrypter = new Encrypter($key, strlen($key) === 16 ? 'aes-128-cbc' : 'aes-256-cbc');
}
return $this->encrypter;
}
/**
* Zwraca odszyfrowaną wartość. Jeśli szyfrowanie jest wyłączone albo
* wartość nie jest naszym szyfrogramem (np. zły klucz, dane wpisane
* ręcznie) - zwraca ją bez zmian.
*/
public function decrypt(?string $value): ?string
{
if ($value === null || $value === '' || ! $this->isConfigured()) {
return $value;
}
try {
return $this->encrypter()->decryptString($value);
} catch (\Throwable) {
return $value;
}
}
/**
* Zwraca zaszyfrowaną wartość. Jeśli szyfrowanie jest wyłączone - zwraca
* bez zmian. Jeśli wartość jest już naszym szyfrogramem - nie szyfruje
* jej ponownie.
*/
public function encrypt(?string $value): ?string
{
if ($value === null || $value === '' || ! $this->isConfigured()) {
return $value;
}
try {
$this->encrypter()->decryptString($value);
return $value; // już zaszyfrowane naszym schematem
} catch (\Throwable) {
// wartość jawna - szyfrujemy
}
return $this->encrypter()->encryptString($value);
}
}