- Hash driver read from HASH_DRIVER (argon2id in production); bcrypt hashes still verify and are rehashed on successful admin/client login since the JWT guard and guard->validate() never rehash on their own. - Client registration uses Hash::make instead of bcrypt(), which always forced bcrypt regardless of the configured driver. - SignRSA now encrypts with Crypt (AES-256-CBC + HMAC, APP_KEY) instead of 3DES in ECB mode without IV. Legacy 3DES values are still readable via RSA_KEY/RSA_PUBLIC until `secrets:reencrypt` migrates them; RSA_PRIVATE is no longer used. - LegacyPortalImporter stored module_vmware.password in plaintext; it is now encrypted, and a migration encrypts existing plaintext rows. Deploy: php artisan migrate, then secrets:reencrypt --dry-run and secrets:reencrypt; remove RSA_* from env once it exits 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
77 lines
1.9 KiB
PHP
77 lines
1.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Services;
|
|
|
|
use Illuminate\Contracts\Encryption\DecryptException;
|
|
use Illuminate\Support\Facades\Crypt;
|
|
|
|
class SignRSA
|
|
{
|
|
private const LEGACY_KEYS = [['rsa.key', 'rsa.public'], ['rsa.previous_key', 'rsa.previous_public']];
|
|
|
|
public function EncryptFunc($plaintext): string
|
|
{
|
|
return Crypt::encryptString((string) $plaintext);
|
|
}
|
|
|
|
public function DecryptFunc($data): string
|
|
{
|
|
if (!$data) {
|
|
return '';
|
|
}
|
|
|
|
try {
|
|
return Crypt::decryptString($data);
|
|
} catch (DecryptException) {
|
|
return $this->decryptLegacy((string) $data);
|
|
}
|
|
}
|
|
|
|
private function decryptLegacy(string $data): string
|
|
{
|
|
$encrypted_data = base64_decode($data);
|
|
|
|
foreach (self::LEGACY_KEYS as [$keyConfig, $publicConfig]) {
|
|
if (!config($keyConfig) || !config($publicConfig)) {
|
|
continue;
|
|
}
|
|
|
|
$verified = $this->Verify_Sign(
|
|
(string) $this->DecryptData($encrypted_data, base64_decode(config($keyConfig))),
|
|
str_replace('\n', "\n", config($publicConfig)),
|
|
);
|
|
|
|
if ($verified !== false) {
|
|
return $verified;
|
|
}
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
private function DecryptData($encrypted_data, $random_key): bool|string
|
|
{
|
|
return openssl_decrypt($encrypted_data, 'DES-EDE3', $random_key, OPENSSL_RAW_DATA);
|
|
}
|
|
|
|
private function Verify_Sign(string $decrypted_data, string $public): string|false
|
|
{
|
|
$data_arr = explode('|', $decrypted_data);
|
|
|
|
if (!isset($data_arr[1])) {
|
|
return false;
|
|
}
|
|
|
|
$signature = base64_decode($data_arr[1]);
|
|
|
|
unset($data_arr[1]);
|
|
|
|
$signature_data = implode('|', $data_arr);
|
|
|
|
$verify = openssl_verify($signature_data, $signature, $public, 'sha256WithRSAEncryption');
|
|
|
|
return $verify === 1 ? $signature_data : false;
|
|
}
|
|
|
|
}
|