NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Sentinel for Laravel

MAC pre vlastné služby

Kruh kľúčov dokáže ručiť aj za správy, ktoré nie sú modelmi ani HTTP požiadavkami — záznamy logov, obsah fronty, vlastné webhooky — od odosielateľov, ktorí s vami zdieľajú tajomstvo, v akomkoľvek jazyku. verifyMac() overí MAC kľúčom, ktorý kid v danom kruhu pomenúva, a vráti jeho KeyInfo (vlastník, label — nikdy materiál), takže správu môžete naviazať na jej odosielateľa:

use RoundlyConsulting\Sentinel\Exceptions\MacVerificationException;

try {
    $key = Sentinel::keys()->ring('logs')->verifyMac($entry['kid'], $payload, $entry['mac']);
} catch (MacVerificationException $exception) {
    report($exception);   // $exception->reason() is a MacRejection
    return;
}

// Bind the key to the sender: one key per sender, its label (or owner) is the sender's identity.
abort_unless($key->label === $entry['service'], 403);

Label aj vlastník sú viazané v obálke kľúča v databáze, takže zapisovateľ do databázy nemôže úpravou riadku presmerovať kľúč na iného odosielateľa: kľúč neprejde kontrolou integrity a verifyMac() odmietne s MacRejection::UnknownKey. Na inštalácii aktualizovanej z 1.1 najprv kľúče prepečaťte a zapnite require_bound_label (pozri Správa kľúčov).

Výpočet MAC

Ľubovoľný odosielateľ ho vypočíta obyčajným HMAC — bez Sentinelu, bez HKDF:

// Node
const mac = crypto.createHmac('sha256', secret).update(payloadBytes).digest('base64url');
// PHP without Sentinel
$mac = rtrim(strtr(base64_encode(hash_hmac('sha256', $payload, $secret, true)), '+/', '-_'), '=');

Odosielateľ v PHP, ktorý má kruh k dispozícii, namiesto toho zavolá mac() — ten počíta aktuálnym podpisovým kľúčom kruhu:

$issued = Sentinel::keys()->ring('logs')->mac($payload);   // IssuedMac, made with the ring's current signing key

$issued->keyId;       // send it along with the message
$issued->mac;         // unpadded base64url
$issued->algorithm;   // Algorithm::HmacSha256

Formát je mac = base64url-bez-paddingu(HMAC(surové tajomstvo, presné bajty správy)) (RFC 4648 §5). Tajomstvo je surový materiál kľúča — bajty za jeho tvarom base64: — použitý tak, ako je, presne ako kľúč HMAC pre RFC 9421, takže odosielateľ potrebuje len tajomstvo. Správa sa hashuje bajt po bajte: normalizujte ju (kódovanie JSON, Unicode NFC) na strane odosielateľa — Sentinel ju nikdy nekóduje znova.

Pravidlá

  • Kruh musí byť nakonfigurovaný a nesmie to byť kruh, ktorý používajú pečate (keys.default_ring), denník (ledger.ring) ani podpisy HTTP správ (signatures.outbound.ring, ring každého profilu) — SealingMisconfiguredException::notAMacRing. Tajomstvá MAC zdieľate s odosielateľmi: v kruhu pečatí či denníka by si odosielateľ mohol odvodiť podkľúče HKDF a falšovať pečate a v kruhu podpisov by MAC nad základom podpisu bol platným HTTP podpisom. Ani pečať nikdy nesmerujte na kruh pre MAC — Sentinel to zo samotného kruhu nespozná.
  • Kid sa hľadá len v danom kruhu: kid iného kruhu — aj s platným MAC pod kľúčom toho kruhu — je unknown_key a reťazec, ktorý nie je platný kid, sa odmietne bez vyhľadávania.
  • Overujú aktívne kľúče a kľúče len na overovanie (vrátane kľúča z konfigurácie, ktorý rotácia presunula do previous, a importovaného kľúča len na overovanie); čakajúce, vyradené a odvolané kľúče — aj cez SENTINEL_REVOKED_KEYS — sa odmietnu.
  • Algoritmus určuje kľúč, nikdy správa: hmac-sha256, prípadne hmac-sha384 / hmac-sha512, ak ich algorithms kruhu povoľuje.
  • Kódovanie je striktné: base64url bez paddingu s presnou dĺžkou hashu kľúča (43 znakov pre SHA-256, 64 pre SHA-384, 86 pre SHA-512). Padding, + či /, medzery, hex, nekanonický posledný znak, prázdny reťazec aj krátky či dlhý MAC sú malformed_mac.
  • Konštantný čas: keď sa nájde použiteľný kľúč, Sentinel vždy vypočíta celý HMAC a porovná ho v konštantnom čase a až potom skontroluje kódovanie a dĺžku — chybne formátovaný MAC stojí toľko isto ako nesprávny a neprejde ani predpona, ani predĺženie správneho MAC.

Odmietnutia

Odmietnutie vyhodí MacVerificationException: reason() je MacRejection, ring() a keyId() uvedú kruh a kid tak, ako boli zadané. Správa výnimky uvedie kruh a ošetrený kid — nikdy MAC, správu ani materiál kľúča. Kontroly idú v poradí: kruh → kid → stav → algoritmus → HMAC a porovnanie → kódovanie a dĺžka → zhoda.

MacRejectionHodnotaKedy
UnknownKeyunknown_keyTaký kid v tomto kruhu nie je — aj kid iného kruhu, neplatný kid, riadok kľúča, ktorý neprejde kontrolou integrity.
PendingKeypending_keyactivates_at je v budúcnosti.
RetiredKeyretired_keyKľúč je vyradený.
RevokedKeyrevoked_keyOdvolaný vo svojom úložisku alebo cez SENTINEL_REVOKED_KEYS.
UnsupportedAlgorithmunsupported_algorithmKľúč je Ed25519 alebo ECDSA, nie hmac-*.
AlgorithmNotAllowedalgorithm_not_allowedHMAC algoritmus kľúča nie je v algorithms kruhu.
Malformedmalformed_macNie je to kanonický base64url bez paddingu alebo nemá plnú dĺžku hashu.
MismatchmismatchSprávne formátovaný, no nie je to MAC tejto správy pod týmto kľúčom.

mac() odmietne s NoSigningKeyException (žiadny aktívny kľúč s tajomstvom — ani odvolaný), AlgorithmNotAllowedException::notHmac (podpisový kľúč je Ed25519 či ECDSA) alebo ::forRing (jeho algoritmus už nie je povolený), plus chyby kruhu uvedené vyššie.

Nastavenie kruhu pre MAC

Kľúč z konfigurácie pre vlastných odosielateľov v PHP a databázové úložisko pre jeden importovaný kľúč na každého externého odosielateľa:

// config/sentinel.php → keys.rings
'logs' => [
    'driver' => 'chain',
    'drivers' => ['config', 'database'],
    'algorithms' => ['hmac-sha256'],
    'key_id' => env('SENTINEL_LOGS_KEY_ID'),
    'key' => env('SENTINEL_LOGS_KEY'),
],
// one verify-only key per sender, bound to it
Sentinel::keys()->ring('logs')->import('billing-2026-10', Algorithm::HmacSha256, 'base64:…', label: 'billing');

Odosielateľa rotujete tak, že importujete jeho ďalší kľúč, odosielateľa naň prepnete a starý kid vyradíte; uniknutý kľúč odvolajte (alebo ho uveďte v SENTINEL_REVOKED_KEYS).

Fasáda, DI a akcia

use RoundlyConsulting\Sentinel\Actions\Keys\VerifyMacAction;

$info   = Sentinel::verifyMac('logs', 'billing-1', $payload, $mac);   // KeyInfo, or MacVerificationException
$issued = Sentinel::mac('logs', $payload);                           // IssuedMac

$this->sentinel->verifyMac('logs', $kid, $payload, $mac);             // an injected SentinelManager
app(VerifyMacAction::class)->execute('logs', $kid, $payload, $mac);   // the raw action

So Sentinel::fake() sa obe volania zaznamenajú a zachovajú produkčné kontroly kruhu, kid, stavu, algoritmu aj kódovania; fakeVerifiedMac(), rejectMacs() a štyri asercie pre MAC ich naskriptujú a overia (pozri Testovanie).

Obmedzenia

  • Prehratie: MAC dokazuje, kto bajty poslal, nie to, že prídu len raz. Do správy chránenej MAC vložte poradové číslo alebo časovú značku a duplikáty odfiltrujte na svojej strane — pomôžu nonce (pozri Nonce a jednorazové URL).
  • Symetria: platný MAC dokáže vytvoriť prijímajúca aplikácia aj každý odosielateľ s rovnakým kľúčom. Každému odosielateľovi dajte vlastný kľúč viazaný labelom alebo vlastníkom, aby sa jeden nemohol vydávať za iného; kde overovateľ nesmie vedieť podpisovať, použite podpisy HTTP s Ed25519.

Testovací vektor pre iné jazyky

Balík obsahuje tests/Fixtures/mac-vector.json: bajty tajomstva 000102…1f (base64:AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=), správu v UTF-8 s ne-ASCII znakmi (presné bajty v message_hex) a MAC Y1UfB_bFvWHrQqhxf-i-W3nf1_GipIV2KqQNdu_aFRk — obsahuje - aj _, takže odosielateľ so štandardným base64 neprejde — plus jedenásť chybných kódovaní. Testy balíka ho overujú obyčajným hash_hmac aj cez node:crypto.

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.