Installation:
composer require fgrosse/phpasn1
Ensure your composer.json enforces PHP 7.4 or lower (due to lack of PHP 8.x support):
"config": {
"platform": {
"php": "7.4"
}
}
First Use Case:
Encode a simple ASN.1 Sequence (e.g., for a CSR or certificate):
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\Integer;
use FG\ASN1\Universal\IA5String;
$sequence = new Sequence(
new Integer(12345),
new IA5String('example.com')
);
$binary = $sequence->getBinary();
$base64 = base64_encode($binary);
Decoding: Parse a base64-encoded ASN.1 payload:
use FG\ASN1\ASNObject;
$binary = base64_decode('MII...'); // Your DER-encoded data
$asnObject = ASNObject::fromBinary($binary);
Key Classes to Know:
FG\ASN1\Universal\* (e.g., Integer, Sequence, Set, ObjectIdentifier).FG\ASN1\TemplateParser (for structured validation).FG\ASN1\OID (predefined Object Identifiers like RSA_ENCRYPTION).Sequence/Set to nest ASN.1 types (e.g., for X.509 certificates):
$subject = new Sequence(
new Set(
new ObjectIdentifier('2.5.4.3'), // CN
new PrintableString('example.com')
),
// ... other fields
);
// app/Services/Asn1/CertificateBuilder.php
class CertificateBuilder {
public function buildSubject(): Sequence {
return new Sequence(
new Set(
new ObjectIdentifier('2.5.4.3'),
new PrintableString('example.com')
)
);
}
}
TemplateParser to enforce schema compliance:
$template = [
Identifier::SEQUENCE => [
Identifier::INTEGER,
Identifier::SEQUENCE => [
Identifier::OBJECT_IDENTIFIER,
Identifier::NULL_OBJECT,
]
]
];
$parser = new TemplateParser();
$object = $parser->parseBinary($binary, $template);
try-catch to handle malformed data:
try {
$object = $parser->parseBinary($binary, $template);
} catch (\Exception $e) {
Log::error("Invalid ASN.1 payload: " . $e->getMessage());
throw new \InvalidArgumentException("Malformed ASN.1 data");
}
// app/Providers/AppServiceProvider.php
public function register() {
$this->app->bind(TemplateParser::class, function () {
return new TemplateParser();
});
}
// app/Http/Middleware/DecodeAsn1Payload.php
public function handle($request, Closure $next) {
if ($request->hasHeader('content-type') && str_contains($request->header('content-type'), 'application/asn.1')) {
$binary = $request->getContent();
$request->merge(['asn1' => ASNObject::fromBinary($binary)]);
}
return $next($request);
}
$privateKey = openssl_pkey_new(['digest_alg' => 'sha256']);
openssl_pkey_export($privateKey, $pem);
$publicKey = openssl_pkey_get_details($privateKey)['key'];
$csr = (new \FG\ASN1\CSR())
->setSubject($subject)
->setPublicKey($publicKey);
$der = $csr->encode();
$asn1Data = $object->toArray(); // Implement toArray() in your model
$model->asn1_data = json_encode($asn1Data);
$model->save();
$storedData = json_decode($model->asn1_data, true);
$object = ASNObject::fromArray($storedData); // Hypothetical method
TemplateParser).FG\ASN1\Certificate).$csrBinary = base64_decode($request->input('csr'));
$csr = $parser->parseBinary($csrBinary, $csrTemplate);
$cert = $ca->sign($csr, $caPrivateKey);
return response()->json(['certificate' => base64_encode($cert->encode())]);
ASNObject::fromBinary().$payload = $legacySystem->fetchPayload();
$asn1 = ASNObject::fromBinary($payload);
$event = new LegacyEvent($asn1->toArray());
event(new LegacyPayloadReceived($event));
$template = buildTemplateFromConfig($config);
$object = $parser->parseBinary($binary, $template);
CertificateGenerated, CsrReceived):
event(new CertificateGenerated($certificate));
ProcessAsn1Job::dispatch($binaryData, $template)->onQueue('asn1');
public function testEncodingDecodingRoundTrip() {
$original = new Sequence(new Integer(123));
$binary = $original->getBinary();
$decoded = ASNObject::fromBinary($binary);
$this->assertEquals($original->toArray(), $decoded->toArray());
}
#[\ReturnTypeWillChange] may cause deprecation warnings or errors.composer.json:
How can I help you explore Laravel packages today?