74 lines
2.0 KiB
PHP
74 lines
2.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Contracts\Encryption\DecryptException;
|
|
use Illuminate\Support\Facades\Crypt;
|
|
|
|
class MailSecretEncrypter
|
|
{
|
|
public function __construct(
|
|
protected ?string $key = null,
|
|
) {
|
|
$this->key = $this->key ?? config('mail_profiles.key');
|
|
if (empty($this->key)) {
|
|
// Fall back to app key for now
|
|
$this->key = config('app.key');
|
|
}
|
|
}
|
|
|
|
public function encrypt(string $plain): string
|
|
{
|
|
// For simplicity use Crypt facade (already uses APP_KEY) unless a dedicated key is set.
|
|
if ($this->usingAppKey()) {
|
|
return Crypt::encryptString($plain);
|
|
}
|
|
|
|
return $this->encryptWithCustomKey($plain);
|
|
}
|
|
|
|
public function decrypt(string $cipher): string
|
|
{
|
|
if ($this->usingAppKey()) {
|
|
return Crypt::decryptString($cipher);
|
|
}
|
|
|
|
return $this->decryptWithCustomKey($cipher);
|
|
}
|
|
|
|
protected function usingAppKey(): bool
|
|
{
|
|
return $this->key === config('app.key');
|
|
}
|
|
|
|
protected function encryptWithCustomKey(string $plain): string
|
|
{
|
|
$iv = random_bytes(openssl_cipher_iv_length('AES-256-CBC'));
|
|
$cipher = openssl_encrypt($plain, 'AES-256-CBC', $this->normalizedKey(), 0, $iv);
|
|
|
|
return base64_encode($iv.'::'.$cipher);
|
|
}
|
|
|
|
protected function decryptWithCustomKey(string $payload): string
|
|
{
|
|
$decoded = base64_decode($payload, true);
|
|
if ($decoded === false || ! str_contains($decoded, '::')) {
|
|
throw new DecryptException('Invalid encrypted payload');
|
|
}
|
|
[$iv, $cipher] = explode('::', $decoded, 2);
|
|
$plain = openssl_decrypt($cipher, 'AES-256-CBC', $this->normalizedKey(), 0, $iv);
|
|
if ($plain === false) {
|
|
throw new DecryptException('Cannot decrypt payload');
|
|
}
|
|
|
|
return $plain;
|
|
}
|
|
|
|
protected function normalizedKey(): string
|
|
{
|
|
$raw = base64_decode($this->key, true);
|
|
|
|
return $raw !== false ? $raw : $this->key; // support base64 or plain
|
|
}
|
|
}
|