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

Certifikáty a reťazce X.509

X509\Certificate parsuje certifikát okamžite pri vytvorení, takže getter už nikdy neskôr nevyhodí chybu parsovania. Vstup je obmedzený na 64 KiB ešte predtým, než ho uvidí OpenSSL, a trieda odpovedá na faktické otázky o certifikáte:

use RoundlyConsulting\Crypto\Facades\Crypto;
use RoundlyConsulting\Crypto\Hash\HashAlgorithm;

$certificate = Crypto::x509()->fromPem($pem);        // also fromDer(), fromBase64() for an x5c entry
$certificate->fingerprint();

$chain = Crypto::x509()->chain()->fromX5c($x5c);     // also fromPems(), fromPemBundle(), fromCertificates()
$chain->isLinked();                                  // the math — the trust call stays yours
$chain->fingerprints(HashAlgorithm::Sha1);

// Shortcuts for the common cases:
Crypto::certificate($pem);
Crypto::chainFromX5c($x5c);
Crypto::chainFromPemBundle($bundle);

Alebo volajte priamo triedy, ktoré fasáda sprístupňuje:

use RoundlyConsulting\Crypto\X509\Certificate;

$certificate = Certificate::fromPem($pem);        // also fromDer(), fromBase64() for an x5c entry

$certificate->commonName();                       // 'app.example'
$certificate->dnsNames();                         // ['app.example', '*.api.example'] — SAN dNSNames, read from the DER
$certificate->fingerprint();                      // lower-case sha256 hex, as openssl emits it
$certificate->notAfter();                         // CarbonImmutable
$certificate->publicKey();                        // RsaKey | EcKey — policy-checked
$certificate->isSignedBy($issuer);                // an ALGORITHM question

fromDer() a fromBase64() prijímajú presne jeden certifikát: bajty za ním sa odmietnu, takže dva rôzne reťazce x5c nikdy nemôžu byť tým istým certifikátom. fromPem() prijíma text PEM, nikdy cestu file://. dnsNames() prechádza GeneralNames rozšírenia subjectAltName priamo v DER a každé dNSName vráti doslovne — nikdy nie text OpenSSL spojený čiarkami, v ktorom by sa jedno meno obsahujúce „, DNS:victim.example“ prečítalo ako dve.

Ďalšie fakty o certifikáte

$certificate->subject()->toString();   // 'CN=leaf.example, O=Acme, C=US'
$certificate->issuer()->commonName;    // DistinguishedName properties
$certificate->serialNumber();          // upper-case hex
$certificate->signatureAlgorithm();    // e.g. 'ecdsa-with-SHA256'
$certificate->version();               // 1, 2 or 3
$certificate->base64();                // the x5c form (standard base64 DER)
$certificate->isSelfSigned();          // the signature math, not a subject == issuer compare
$certificate->equals($other);          // constant-time DER comparison

$extension = $certificate->extension('1.2.840.113635.100.8.2');   // ?Extension
$extension?->critical;                 // bool
$extension?->der;                      // raw, uninterpreted extension bytes
$certificate->extensions();            // every extension, keyed by OID

extension() vracia surové DER vnútri rozšírenia spolu s príznakom kritickosti — prečítané z vlastného DER certifikátu, pretože openssl_x509_parse() prevádza neznáme rozšírenia na stratový text. Tieto bajty dekódujte dekodérom ASN.1 / DER.

Dátumy platnosti

Platnosť sa hlási ako dátumy so symetrickou toleranciou posunu hodín, ktorú určujete vy. Okamih je predvolene teraz (rešpektuje Carbon::setTestNow) a prijíma ľubovoľný DateTimeInterface, takže môžete vyhodnocovať voči času podpisu samotného tokenu:

$certificate->isValidAt();                                  // now (honours Carbon::setTestNow)
$certificate->isValidAt($token->signedAt, leewaySeconds: 60);
$certificate->isExpiredAt(leewaySeconds: 60);              // distinct from a bad signature
$certificate->isNotYetValidAt();                            // a negative leeway throws

Záporná tolerancia vyhodí InvalidLeewayException. Samostatné isExpiredAt() a isNotYetValidAt() umožňujú vyhodiť rozlíšené chyby — expirovaný certifikát nesmie vyzerať ako neplatný podpis. Dátumy nič iné neblokujú: aj expirovaný certifikát stále vydá svoj verejný kľúč a fakty.

Reťazce

X509\Chain je usporiadaný zoznam od listu po koreň s najviac 10 certifikátmi (Chain::MAX_CERTIFICATES). Zostavíte ho z hlavičky JOSE x5c, z PEM balíka alebo zo zoznamu PEM:

use RoundlyConsulting\Crypto\Hash\HashAlgorithm;
use RoundlyConsulting\Crypto\X509\Chain;

// A JOSE x5c chain (leaf first), a concatenated PEM bundle, or a list of PEMs:
$chain = Chain::fromX5c($x5c);                    // ≤ 10 certificates, strict base64, typed errors
$chain = Chain::fromPemBundle($bundle);
$chain = Chain::fromPems([$leafPem, $intermediatePem, $rootPem]);

$chain->isLinked();                               // every cert is signed by the next one up
$chain->fingerprints(HashAlgorithm::Sha1);        // leaf → root
$chain->leaf()->publicKey();
$chain->root();                                   // the LAST certificate — not "a trusted root"
$chain->get(1);                                   // by index
count($chain);                                    // Countable; foreach works too
$chain->pemBundle();

isLinked() je čistá matematika — každý certifikát je podpísaný nasledujúcim a reťazec s jedným certifikátom je triviálne prepojený. fromPemBundle() spočíta PEM bloky skôr, než niektorý z nich parsuje, takže príliš veľký balík stojí jeden regex, nie jedenásť parsovaní.

Prehľad metód certifikátu

MetódaVracia
fromPem() / fromDer() / fromBase64()Certificate. fromBase64() prijíma položku x5c — štandardné base64 s paddingom z DER, nie base64url. Vstup DER musí byť presne jeden certifikát; vstup PEM je text, nikdy cesta.
pem() / der() / base64()Kódovania PEM, DER a x5c (base64).
fingerprint($algorithm = Sha256)Hex malými písmenami bez dvojbodiek, bajtovo zhodný s openssl_x509_fingerprint().
publicKey()RsaKey alebo EcKey po kontrole politiky. Certifikáty Ed25519 nie sú podporované.
subject() / issuer()DistinguishedName (CN, O, OU, C, ST, L) s toString().
commonName() / dnsNames()CN subjektu; položky dNSName zo subjectAltName prečítané z DER — doslovne (vrátane wildcardov), v poradí zakódovania.
extension($oid) / extensions()?Extension (oid, critical, der); všetky rozšírenia podľa OID v poradí zakódovania.
version() / serialNumber() / signatureAlgorithm()1, 2 alebo 3; hex veľkými písmenami; názov podpisového algoritmu.
notBefore() / notAfter()CarbonImmutable.
isValidAt() / isExpiredAt() / isNotYetValidAt()Predikáty dátumov s voliteľným okamihom a toleranciou v sekundách.
isSignedBy($issuer) / isSelfSigned()Matematika podpisu — isSelfSigned() nie je reťazcové porovnanie subjekt == vydavateľ.
equals($other)Porovnanie DER v konštantnom čase.

Hranica dôvery

Balík overí matematiku; o tom, čomu dôverovať, rozhodujete vy. Neexistuje isTrusted(), pinning, úložisko koreňových certifikátov, revokácia ani porovnávanie hostname — zámerne, a vynucuje to architektonický test. root() je jednoducho posledný certifikát, nie autorita, ktorú poznáte. Pripnite si vlastné kotvy a rozhodnite, čo pre vás znamená expirovaný certifikát.

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.