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 s vlastnými tajomstvami

Kruhy kľúčov kľúč spravujú: Sentinel ho vygeneruje, uloží, rotuje aj odvolá. Niektoré tajomstvá však patria vašej aplikácii — jedno na každý endpoint webhookov, zašifrované v jeho riadku a rotované s prechodným obdobím, alebo tajomstvo, ktoré vám odovzdal partner, často kratšie než 32 bajtov. Sentinel::macs() nimi podpisuje a overuje. Nepotrebuje kruh kľúčov, tabuľku ani nakonfigurovaný kľúč a nič neukladá:

use RoundlyConsulting\Sentinel\Enums\Algorithm;
use RoundlyConsulting\Sentinel\Facades\Sentinel;

$mac = Sentinel::macs()->sign($payload, $endpoint->secret);                      // raw bytes, HMAC-SHA256
$mac = Sentinel::macs()->sign($payload, $endpoint->secret, Algorithm::HmacSha512);

$header = 'v1,'.base64_encode($mac);                                               // the wire format is yours

// Receiving: the current secret first, then the ones still in their grace period.
$index = Sentinel::macs()->verify($payload, base64_decode($signature), [$current, $previous]);

abort_if($index === null, 401);   // 0 = current, 1 = previous

Kedy použiť ktoré

PotrebujetePoužite
Aby kľúč spravoval Sentinel — vygeneroval, uložil zašifrovaný, rotoval, odvolal a naviazal na odosielateľaKruh pre MAC: keys()->ring($ring)->mac() / verifyMac() (pozri MAC pre vlastné služby)
Vlastné tajomstvo uložené tam, kde ho máte, ľubovoľnej dĺžky, počas rotácie viacero narazSentinel::macs()

Pravidlá

  • Obyčajný HMAC: HMAC(tajomstvo, presné bajty správy) s tajomstvom tak, ako je — bez HKDF, bez označenia účelu —, takže ho protistrana v akomkoľvek jazyku zopakuje štandardnou knižnicou.
  • Dnu aj von surové bajty: sign() vráti 32, 48 alebo 64 bajtov (hmac-sha256 — predvolený —, hmac-sha384, hmac-sha512) a verify() prijíma surový MAC. Base64, hex či base64url je váš formát prenosu.
  • Len HMAC: Ed25519 a ECDSA vyhodia AlgorithmNotAllowedException::notHmacForMacs().
  • Akékoľvek neprázdne tajomstvo: neplatí spodná hranica 32 bajtov (tá ostáva pri kľúčoch kruhov) ani horná (HMAC príliš dlhý kľúč zahašuje). Prázdne tajomstvo vyhodí InvalidKeyMaterialException::emptySecret() — pri každom tajomstve v zozname, skôr než sa vypočíta akýkoľvek MAC, aj keď stojí až za zhodou. Za silu tajomstva zodpovedáte vy: vlastné tajomstvá generujte aspoň z 32 náhodných bajtov (random_bytes(32)); krátke tajomstvo, ktoré ste dostali, je len také silné, aké je.
  • 1 až 8 tajomstiev: prázdny zoznam vyhodí InvalidKeyMaterialException::noSecrets(), viac než MacsAccessor::MAX_SECRETS (8) ::tooManySecrets() a pole, ktoré nie je zoznamom alebo obsahuje niečo iné než reťazec, InvalidArgumentException.
  • Výsledkom je najnižší index tajomstva, ktoré MAC vytvorilo (rovnaké tajomstvo dvakrát → prvé), alebo null. MAC nesprávnej dĺžky — aj prázdny — je null, nikdy výnimka.
  • Bez predčasného ukončenia: verify() vypočíta a v konštantnom čase porovná MAC každého tajomstva, slučku nikdy neopustí skôr a index vyberie až z nahromadeného výsledku — z času sa nedá zistiť, ktoré tajomstvo sa zhodovalo, ani či vôbec nejaké. MAC nesprávnej dĺžky sa porovná s nulami správnej dĺžky, takže stojí toľko isto ako nesprávny.
  • Rotácia je zoznam: [$current, $previous] počas prechodného obdobia, potom [$current]. Podpisujte len aktuálnym tajomstvom.
  • Nič sa neukladá ani neloguje a odmietnutia nikdy neobsahujú tajomstvo, MAC ani správu. Tajomstvá aj MAC sú označené #[\SensitiveParameter] v každej vrstve, vrátane vlastného rámca fasády pri plochom volaní.

Odmietnutia

Každé pravidlo sa skontroluje skôr, než sa vypočíta akýkoľvek MAC. Štyri výnimky Sentinelu majú preložené správy (sentinel::messages.macs.*, anglicky a slovensky):

VýnimkaKedy
AlgorithmNotAllowedException::notHmacForMacs()sign() alebo verify() s Ed25519 či ECDSA.
InvalidKeyMaterialException::emptySecret()Prázdne tajomstvo — pri podpisovaní alebo kdekoľvek v zozname.
InvalidKeyMaterialException::noSecrets()verify() s prázdnym zoznamom.
InvalidKeyMaterialException::tooManySecrets()verify() s viac než 8 tajomstvami.
InvalidArgumentExceptionTajomstvá, ktoré nie sú zoznamom reťazcov — reťazcové kľúče, medzery v indexoch, prvok, ktorý nie je reťazec.

Fasáda, DI a akcie

use RoundlyConsulting\Sentinel\Actions\Macs\SignWithSecretAction;
use RoundlyConsulting\Sentinel\Actions\Macs\VerifyWithSecretsAction;

$mac   = Sentinel::signWithSecret($payload, $secret);                                  // flat
$index = Sentinel::verifyWithSecrets($payload, $mac, [$current, $previous]);

$index = $this->sentinel->macs()->verify($payload, $mac, [$current, $previous]);       // an injected SentinelManager

$mac   = app(SignWithSecretAction::class)->execute($payload, $secret);                  // the raw actions
$index = app(VerifyWithSecretsAction::class)->execute($payload, $mac, [$current, $previous]);
MetódaVraciaČo robí
macs()MacsAccessorsign() a verify() s tajomstvami, ktoré drží vaša aplikácia.
signWithSecret(string $message, string $secret, Algorithm $algorithm = Algorithm::HmacSha256)stringSurový MAC (32 / 48 / 64 bajtov).
verifyWithSecrets(string $message, string $mac, array $secrets, Algorithm $algorithm = Algorithm::HmacSha256)?intNajnižší index z 1–8 tajomstiev, ktorému surový MAC zodpovedá, inak null — v konštantnom čase cez všetky tajomstvá.

Každé volanie ide cez manažéra, takže naviazanie ktorejkoľvek z oboch akcií v kontajneri platí všade a Sentinel::fake() vidí fasádu, prístup aj injektovaný SentinelManager rovnako.

Prehratie a symetria

  • Prehratie nepokrýva, rovnako ako MAC s kľúčmi kruhu: MAC dokazuje, kto bajty poslal, nie to, že prídu len raz. Spolu s obsahom zahrňte do MAC časovú značku alebo id správy a duplikáty odfiltrujte na svojej strane — urobia to idempotenčné kľúče Sentinelu (pozri Idempotenčné kľúče).
  • Kto overuje, má tajomstvo a vie pod ním MAC aj sfalšovať. Každé tajomstvo uchovávajte zašifrované — cast encrypted — a každému odosielateľovi dajte vlastné.

Testovanie

Sentinel::macs() je bezstavový, preto ho Sentinel::fake() nepodvrhuje: sign() a verify() spustia skutočné akcie — každé pravidlo, rovnaké výnimky — a vrátia skutočný MAC a index, bajt po bajte. Každé volanie sa zaznamená bez tajomstiev (signWithSecret so správou a algoritmom, verifyWithSecrets so správou, algoritmom a počtom tajomstiev); MAC odovzdaný do verify() sa tiež nezaznamená a odmietnuté volanie nezaznamená nič. rejectMacsWithSecrets() zariadi, že každé verify() vráti null, takže cestu k 401 otestujete bez falšovania MAC:

use RoundlyConsulting\Sentinel\Enums\Algorithm;

$fake = Sentinel::fake();

$mac = Sentinel::macs()->sign('{"id":1}', $secret);       // the real MAC, byte for byte
$fake->assertMacSigned('{"id":1}', Algorithm::HmacSha256);

$fake->rejectMacsWithSecrets();
$this->postJson('/webhooks/acme', $payload, ['Webhook-Signature' => 'v1,bogus'])->assertUnauthorized();
$fake->assertMacsVerified(matched: false);

Volania overia assertMacSigned(?string $message = null, ?Algorithm $algorithm = null), assertMacsVerified(?string $message = null, ?bool $matched = null) — true, ak sa niektoré tajomstvo zhodovalo, false, ak žiadne, null pre oboje — a assertNoMacsWithSecrets(); pozri Testovanie.

Testovacie vektory pre iné jazyky

Balík obsahuje tests/Fixtures/macs-vectors.json s M-1…M-8: testovací prípad 2 z RFC 4231 (4-bajtový kľúč Jefe) pre všetky tri hashe, testovací prípad 6 (131-bajtový kľúč), 1-bajtový kľúč, príklad Standard Webhooks (24-bajtové tajomstvo) a dve 32-bajtové tajomstvá pre prípad rotácie — nezávisle vypočítané cez hash_hmac v PHP.

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.