Search by

phil / open-badges

phil

Open Badges 3.0 and CLR 2.0 credentials: issued as Verifiable Credentials 2.0, signed as JSON Web Tokens (EdDSA, RS256) or with an eddsa-rdfc-2022 Data Integrity proof, verified offline, baked into PNG and SVG images, revoked through a Bitstring Status List, endorsed by third parties and gathered in

0.1.0-alpha 2026-11-11 06:11 UTC

This package is auto-updated.

Last update: 2026-11-11 13:32:01 UTC


README

Open Badges 3.0 that anyone can verify: issued, signed, baked into the image, revoked, endorsed and gathered in a learner record.

phil/open-badges issues Open Badges 3.0 credentials — an OpenBadgeCredential in the data model of Verifiable Credentials 2.0 — and verifies them. A credential says that an issuer recognizes an achievement of a recipient; it is signed by the issuer's key, so that the recipient can take it anywhere — a portfolio, a professional profile, a wallet — and anyone can check it with the issuer's public key, without asking the site that issued it.

It is for any PHP application that recognizes what people do: a training platform that awards certificates, a community that thanks its volunteers, an event that credits its speakers. The library reads no account and stores nothing: the application says who the recipient is, as they give it, and keeps what it issued.

It is a plain PHP library that requires only PHP and its extensions. A credential is secured in one of the two ways Open Badges 3.0 recognizes: as a JSON Web Token (EdDSA or RS256), or with an embedded Data Integrity proof of the eddsa-rdfc-2022 cryptosuite, for which the library carries its own JSON-LD processor and RDF canonicalization. Verifying never fetches anything: the JSON-LD contexts are bundled, and the keys are the ones the application gives.

Status

Part State
Issuers, achievements, recipients (DID, hashed e-mail address or URL), OpenBadgeCredential Implemented and tested
VC-JWT with EdDSA (Ed25519) and RS256 (RSA of 2048 bits or more) Implemented and tested
Data Integrity eddsa-rdfc-2022, JSON-LD in safe mode, RDFC-1.0 canonicalization Implemented and tested against the W3C vectors
Baking into PNG (iTXt) and SVG, reading back Implemented, tested and fuzzed
Revocation and suspension through a Bitstring Status List Implemented and tested
Endorsements, Comprehensive Learner Record 2.0 Implemented and tested
The 1EdTech conformance validator Not run yet: it is part of the release
Open Badges 2.0, eddsa-jcs-2022, ECDSA cryptosuites, the 1EdTech revocation list Not started
A Symfony bundle: the issuer's profile and keys served, the status lists, a verification page Implemented in phil/open-badges-bundle

Documentation

Document What it covers
Installation Requirements, installing, the keys.
Issuing Issuers, achievements, recipients, credentials.
Securing JSON Web Tokens and Data Integrity proofs, the profile document.
Verifying CredentialVerifier, verification methods, the recipient, the JSON-LD subset.
Baking A credential in a PNG or an SVG image.
Revocation Status entries, status lists and their credential.
Endorsements and learner records EndorsementCredential and CLR 2.0.
Extension points Signers, verification methods, context loaders.
Exceptions OpenBadgesException and its three exceptions.
Testing The library's tests, vectors, fuzz targets and benchmark.
Reference Every type of the library, with its role.

Quick start

composer require phil/open-badges
use Phil\OpenBadges\Achievement;
use Phil\OpenBadges\CredentialIssuer;
use Phil\OpenBadges\DataIntegrity\EddsaRdfc2022;
use Phil\OpenBadges\Issuer;
use Phil\OpenBadges\Key\Ed25519Signer;
use Phil\OpenBadges\Recipient;

$signer = Ed25519Signer::fromSeed($seed);              // 32 secret bytes
$issuer = new CredentialIssuer(new Issuer('https://example.org/issuer', 'Example'), $signer, 'https://example.org/issuer#key-1');
$achievement = new Achievement('https://example.org/badges/mentor', 'Mentor', 'Guided five newcomers.', 'Guide five newcomers through their first month.');
$recipient = Recipient::email($emailTheyGave, bin2hex(random_bytes(8)));

$token = $issuer->issue($achievement, $recipient, 'urn:uuid:'.$uuid, $awardedAt);     // VC-JWT

$document = new EddsaRdfc2022()->sign(                                                // Data Integrity
    $issuer->credential($achievement, $recipient, 'urn:uuid:'.$uuid, $awardedAt),
    $signer,
    'https://example.org/issuer#key-1',
    $now,
);

Requirements

PHP 8.5 or later with the dom, json, libxml, mbstring, openssl, sodium and zlib extensions.

Contributing

Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.

License

MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Parler Haut Interagir Librement project. See LICENSE. The bundled JSON-LD contexts keep their own notices: see NOTICE.