sop/crypto-types
Strongly typed cryptocurrency value objects and Eloquent casts for Laravel. Store, convert, and compare Bitcoin, satoshi, and fiat amounts safely with immutable types that avoid floating-point rounding errors in your models and domain code.
sop/crypto-types is a small, focused library: it gives you typed PHP objects for the ASN.1 structures that show up in crypto formats (algorithm identifiers and their parameters, signature blobs, key/SPKI-style containers, OID-bearing values). It sits on top of sop/asn1, which does the DER/BER wire encoding; this package adds the semantic layer so you are not juggling raw Element trees everywhere.
Install and inspect
composer require sop/crypto-types
It's MIT-licensed and small (11 stars on the upstream repo), so treat the source as the documentation. First stops:
composer.json — confirm the PHP constraint and the exact sop/asn1 version it pins.src/ — particularly the AlgorithmIdentifier namespace; that is the type you will touch most.tests/ — for a package this size the test suite is the best usage guide; it shows real DER fixtures and round-trips.Sop\CryptoTypes\...) and any factory/registry entry point.Minimal first use case: turn an OpenSSL blob into a typed object
The most common day-to-day job is taking DER bytes produced by OpenSSL (or by PHP's openssl_* functions) and lifting them into a typed object you can branch on, then encoding back out.
use Sop\Asn1\Element;
use Sop\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
// PEM -> DER (strip armour, base64-decode)
$der = base64_decode(preg_replace('/-----[^-]+-----|\s+/', '', $pem));
$alg = AlgorithmIdentifier::fromASN1(Element::fromDER($der));
$alg->oid(); // e.g. "1.2.840.113549.1.1.11"
$alg->name(); // human-readable algorithm name
$derAgain = $alg->toASN1()->toDER();
Verify the exact method names against src/ before you build on them — the fromASN1() / toASN1() pair is the convention throughout the SOP family, but the accessor names (oid(), name(), parameters()) are the parts most likely to drift between minor versions.
A good first concrete task: parse the SubjectPublicKeyInfo algorithm field out of a certificate or public key, assert the OID matches what your application expects, and reject everything else. That exercises decode, typed inspection, and a policy check in about fifteen lines.
Decode at the boundary, work in types internally. Treat DER as an I/O format. Parse once when data enters your application (uploaded certificate, JWT header, key file), convert OIDs and parameters into your own DTOs/enums, and never pass raw Element trees deeper into business logic. Encode back to DER only at the edge (persistence, signing, HTTP responses). This keeps the ASN.1 dependency contained to one adapter layer and makes it trivial to swap or upgrade the library later.
Round-trip everything in tests. The single most valuable habit with this package is asserting parse(encode(x)) == x and encode(parse(der)) === der against fixed DER fixtures captured from OpenSSL:
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out key.pem
openssl pkey -in key.pem -pubout -outform DER -out pub.der
Commit those .der files. When you upgrade sop/asn1 or this package, byte-for-byte equality on re-encode is the fastest way to catch a regression in default parameter handling.
Use the factory/registry rather than instanceof chains. These libraries typically expose a factory that maps an OID to a concrete AlgorithmIdentifier subclass. Route unknown OIDs through the generic fallback class instead of throwing, then apply your allow-list at a higher level. That keeps the library forward-compatible while your application stays strict.
Compose with OpenSSL rather than replacing it. This package is glue, not a crypto engine. openssl_pkey_get_details(), openssl_x509_parse(), and openssl_csr_new() still do the heavy lifting; use sop/crypto-types when you need to read or construct a structure that OpenSSL's PHP bindings don't expose (algorithm parameters, raw signature encodings, custom OIDs). A typical workflow is: generate with OpenSSL → export DER → parse with this library → inspect/policy-check → reconstruct a new structure → hand back to OpenSSL or a higher-level SOP package (e.g. sop/x509) for signing.
Convert PEM centrally. Every integration point needs PEM↔DER. Write one helper pair (pemToDer, derToPem with 64-column base64 and correct -----BEGIN X----- labels) and reuse it; the label matters because consumers infer the type from it.
Keep value objects immutable. Build new instances from primitives rather than mutating parsed ones. If you need to alter an algorithm identifier, construct the desired subclass directly and encode it — this avoids partial-state bugs when parameters don't match the algorithm.
NULL. RSA AlgorithmIdentifier parameters are conventionally an explicit NULL; ECDSA/EdDSA parameters are absent. Be lenient on input (accept both where the RFC permits) and strict on output (emit what the spec mandates), or third-party verifiers will reject your structures.0x00, and large numbers will overflow PHP int. Handle them with gmp or brick/math, not native arithmetic.BIT STRINGs; getting the unused-bits octet wrong yields keys that look valid until they don't. Round-trip the bytes, don't rebuild them.Z suffix, and the 2049 pivot. If you touch time-bearing structures, parse with an explicit rule and test the boundary.composer.json, check the sop/asn1 transitive pin, and keep your own DER fixture tests so an upstream bump can't silently change encoding. The MIT license and small codebase make vendoring or forking viable if the project stalls.ext-openssl. Fine for per-request certificate handling; cache parsed objects (or your DTOs) if you're parsing the same key material in a loop.bin2hex() and inspect with openssl asn1parse -inform DER -in file.der -i. The offset output usually tells you instantly whether you have a length problem, a wrong label, or a truncated blob.AlgorithmIdentifier subclasses, use it for private/proprietary OIDs rather than editing vendor code — that is the upgrade-safe seam.How can I help you explore Laravel packages today?