Files
laravel-gost-template/app/Models/PersonalData.php
2026-06-24 17:20:43 +09:00

104 lines
2.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Models;
use App\Models\Concerns\HasPdnEncryption;
use Database\Factories\PersonalDataFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* ПРИМЕР модели с персональными данными (УЗ-1).
*
* Меры ФСТЭК: ЗНИ (шифрование полей), ОЦЛ.2 (контроль целостности через
* контрольную сумму), УПД.2 (разграничение доступа через PersonalDataPolicy).
*
* @property int $id
* @property int|null $owner_id
* @property string|null $last_name
* @property string|null $first_name
* @property string|null $passport
* @property string|null $snils
*/
class PersonalData extends Model
{
/** @use HasFactory<PersonalDataFactory> */
use HasFactory;
use HasPdnEncryption;
use SoftDeletes;
protected $table = 'personal_data';
protected $fillable = [
'owner_id',
'subject_pseudonym',
'last_name',
'first_name',
'middle_name',
'birth_date',
'passport',
'snils',
'phone',
];
/**
* Шифруемые поля ПДн (мера ЗНИ).
*
* @var array<int, string>
*/
protected array $encrypted = [
'last_name',
'first_name',
'middle_name',
'birth_date',
'passport',
'snils',
'phone',
];
protected static function booted(): void
{
// Контроль целостности (ОЦЛ.2): пересчёт контрольной суммы при сохранении.
static::saving(function (PersonalData $model): void {
$model->checksum = $model->calculateChecksum();
});
}
/**
* @return BelongsTo<User, $this>
*/
public function owner(): BelongsTo
{
return $this->belongsTo(User::class, 'owner_id');
}
/**
* HMAC по расшифрованному содержимому ПДн-полей — для проверки целостности.
*/
public function calculateChecksum(): string
{
$payload = [];
foreach ($this->encrypted as $attribute) {
$payload[$attribute] = $this->getAttribute($attribute);
}
$key = (string) config('audit.hmac_key');
$key = str_starts_with($key, 'base64:') ? (string) base64_decode(substr($key, 7), true) : $key;
return hash_hmac('sha256', (string) json_encode($payload, JSON_UNESCAPED_UNICODE), $key);
}
/**
* Проверка целостности записи (ОЦЛ.2).
*/
public function integrityValid(): bool
{
return $this->checksum !== null
&& hash_equals($this->checksum, $this->calculateChecksum());
}
}