Detailed Description
A strongly typed reader for the 51Did (51Degrees Identifier) returned by the 51Degrees Cloud service.
A 51Did is described at three levels. The 51Did is the identifier as a whole. The envelope is the signed {
- See also
- Owid} that carries it (version, domain, date, payload, signature), re-issued fresh on every call. The match key is the stable, comparable part of the payload after the Flags and License Id, exposed via {
- FodId::getMatchKey()}. Two 51Dids for the same inputs share the same match key even though their envelopes differ. Compare match keys, never envelopes. The name follows the Model Terms for Marketing, which call that part of a 51Did the match key.
Payload layout. The header (offsets 0-4) is shared by every identifier type, and bits 6-7 of Flags select the {
- See also
- IdType} and the length of the match key that follows. An identifier carrying a creator context has a further section after the match key, which the reader keeps in the payload and does not interpret. There is no upper bound on the payload here, because the lengths of that section belong to the cloud and an older reader has to keep accepting an identifier from a newer one. The byte structure is specified at https://github.com/51Degrees/specifications/blob/main/did-specification/identifier-layout.md which is the authority for it, and the surface every 51Did package offers is listed at https://github.com/51Degrees/specifications/blob/main/did-specification/package-surface.md
Every field is read through a named accessor, being {
- See also
- FodId::getType()}, {
- FodId::getUsage()}, {
- FodId::isUsageIndirect()}, {
- FodId::getLicenseId()} and {
- FodId::getMatchKey()}. The raw flags byte and the byte offsets are not offered, because reading the usage bits by hand gets the answer backwards, as {
- Usage} explains.
One byte after the match key holds the {
- See also
- Terms} the identifier was created under, read through {
- FodId::getTerms()}. A payload that ends at the match key carries no Terms byte and reads as a Terms of zero, so nothing has to tell an absent byte from a zero one and no presence flag exists.
Bits 4 and 5 of the flags byte say which payload layout the identifier follows, and this package reads version 0. A payload naming any other version is refused with {
- See also
- FodIdParseStatus::UnsupportedPayloadVersion} rather than read under the layout this package knows, because a later version exists precisely because a field moved, so reading one here would answer with values that are wrong rather than absent. The version is not exposed, because a caller has nothing to decide with it.
Reading is two steps. The OWID library reads the envelope and this class then reads the payload inside it. The try factories, {
- See also
- FodId::tryFromBase64()}, {
- FodId::tryFromByteArray()} and {
- FodId::tryFromOwid()}, answer with a {
- FodIdParseResult} rather than raising, because the text arrives from outside and failing to be a 51Did is an ordinary outcome, and whoever sends the text chooses how often that happens. The older factories, {
- FodId::fromBase64()}, {
- FodId::fromByteArray()}, {
- FodId::fromOwid()} and the constructor, raise for the same inputs and are kept for callers written against them. Both run the same checks.
The cloud issues a 51Did in standard base64 with padding, and a page puts one in a link in the URL-safe alphabet without padding, so the base64 factories accept either form and {
- See also
- FodId::asBase64Url()} produces the URL-safe one.
The owid-php {
- See also
- Owid} is
final, so this type composes an OWID (holds the envelope and delegates OWID-level concerns to it) rather than inheriting from it. An OWID only exists once it has been read or signed and its fields are read only, so the one handed in is held as it is. Reading a { - FodId} does not verify the signature, and a parsed 51Did is not necessarily genuine. Call {
- FodId::verify()} or {
- FodId::signatureStatus()} explicitly.
Public Member Functions | |
| __construct (Owid $owid) | |
| Promotes an already-read {. | |
| getType () | |
| The identifier type carried in bits 6-7 of the flags byte. | |
| getUsage () | |
| The usage carried in bits 0-2 of the flags byte, as the highest usage granted. | |
| isUsageIndirect () | |
| Whether the usage is indirect, being worked out by the issuer from a signal other than the caller stating it, rather than direct, being stated by the caller. | |
| getLicenseId () | |
| The 4-byte little-endian License Id field (0 to 4294967295). | |
| getMatchKey () | |
| The match key from the payload (a 32-byte SHA-256 for Probabilistic and HashedEmail identifiers, or 16 GUID bytes for Random) as a binary string. | |
| getTerms () | |
| The address of the terms document this identifier was created under, read from the byte after the match key, or null where the identifier names no document this package knows. | |
| getVersion () | |
| The OWID version. | |
| getDomain () | |
| The domain of the OWID creator. | |
| getDate () | |
| The OWID creation date. | |
| getPayload () | |
| The OWID payload bytes. | |
| getSignature () | |
| The 64-byte OWID signature. | |
| asBase64 () | |
| Returns the OWID as a base64 string in the standard alphabet with padding, as the cloud issues it. | |
| asBase64Url () | |
Returns the OWID as a base64 string in the URL-safe alphabet (- and _) without padding, so it can go in a URL without further encoding. | |
| asByteArray () | |
| Returns the OWID as a byte array including the signature. | |
| verify (string $publicPem) | |
| Verifies the OWID signature against the supplied public key. | |
| signatureStatus (string $publicPem) | |
| Says whether the signature is genuine for the public key given, and where the question could not be answered, says that instead of reporting a forgery. | |
Static Public Member Functions | |
| static | tryFromBase64 (mixed $value) |
| Reads a 51Did from its base64-encoded OWID string, answering rather than raising when the value is not one. | |
| static | tryFromByteArray (mixed $buffer) |
| Reads a 51Did from the raw bytes of an OWID envelope, answering rather than raising when the bytes are not one. | |
| static | tryFromOwid (Owid $owid) |
| Reads a 51Did from an already-read {. | |
| static | fromBase64 (string $base64) |
| Parses a 51Did from its base64-encoded OWID string, in either alphabet, with or without padding, and raises when the value is not one. | |
| static | toStandardBase64 (string $value) |
| Restores a string in either base64 alphabet to the standard alphabet with padding. | |
| static | fromByteArray (string $buffer) |
| Parses a 51Did from the raw bytes of an OWID envelope and raises when the bytes are not one. | |
| static | fromOwid (Owid $owid) |
| Promotes an already-read OWID into a 51Did, raising when its payload does not fit. | |
Constructor & Destructor Documentation
◆ __construct()
| fiftyone\pipeline\did\FodId::__construct | ( | Owid | $owid | ) |
Promotes an already-read {.
- See also
- Owid} into a 51Did by unpacking its payload.
A payload must be at least the base length for its identifier type. Anything beyond the base is a creator context section, whose exact lengths belong to the cloud, so any longer payload is accepted here. {
- See also
- FodId::tryFromOwid()} answers with a status where this raises.
- Exceptions
-
InvalidArgumentException when the payload is shorter than the header, or than the minimum for its identifier type, names a payload version this package does not know, or has usage bits 000.
Member Function Documentation
◆ asBase64()
| fiftyone\pipeline\did\FodId::asBase64 | ( | ) |
Returns the OWID as a base64 string in the standard alphabet with padding, as the cloud issues it.
- Exceptions
-
OwidException
◆ asBase64Url()
| fiftyone\pipeline\did\FodId::asBase64Url | ( | ) |
Returns the OWID as a base64 string in the URL-safe alphabet (- and _) without padding, so it can go in a URL without further encoding.
{
- See also
- FodId::fromBase64()} and {
- FodId::tryFromBase64()} read this form back.
- Exceptions
-
OwidException
◆ asByteArray()
| fiftyone\pipeline\did\FodId::asByteArray | ( | ) |
Returns the OWID as a byte array including the signature.
- Exceptions
-
OwidException
◆ fromBase64()
|
static |
Parses a 51Did from its base64-encoded OWID string, in either alphabet, with or without padding, and raises when the value is not one.
{
- See also
- FodId::tryFromBase64()} answers with a status for the same inputs and is the surface to use for values arriving from outside.
- Exceptions
-
OwidException when the string is not valid base64 or not a valid OWID, with the message naming the OWID library's status. InvalidArgumentException when the envelope is sound and the payload does not fit a 51Did.
◆ fromByteArray()
|
static |
Parses a 51Did from the raw bytes of an OWID envelope and raises when the bytes are not one.
{
- See also
- FodId::tryFromByteArray()} answers with a status for the same inputs.
- Exceptions
-
OwidException when the bytes are not a valid OWID, with the message naming the OWID library's status. InvalidArgumentException when the envelope is sound and the payload does not fit a 51Did.
◆ fromOwid()
|
static |
Promotes an already-read OWID into a 51Did, raising when its payload does not fit.
The same as the constructor, kept as the named form.
- Exceptions
-
InvalidArgumentException when the payload is shorter than the header, or than the minimum for its identifier type, names a payload version this package does not know, or has usage bits 000.
◆ getLicenseId()
| fiftyone\pipeline\did\FodId::getLicenseId | ( | ) |
The 4-byte little-endian License Id field (0 to 4294967295).
On an identifier carrying a creator context the four bytes at offset 1 hold an encrypted value that only 51Degrees can turn back into a licence identifier, so this is the field's raw value and identifies nothing outside 51Degrees.
◆ getMatchKey()
| fiftyone\pipeline\did\FodId::getMatchKey | ( | ) |
The match key from the payload (a 32-byte SHA-256 for Probabilistic and HashedEmail identifiers, or 16 GUID bytes for Random) as a binary string.
This is the stable, comparable part of the envelope. Two 51Dids for the same inputs share the same match key even though their envelopes (date, signature) differ on every issue, so use the match key as the cache and dedup key.
◆ getTerms()
| fiftyone\pipeline\did\FodId::getTerms | ( | ) |
The address of the terms document this identifier was created under, read from the byte after the match key, or null where the identifier names no document this package knows.
The byte is an index into a table in the specification and this package turns the index into the address, so a caller never handles the byte. The address is answered and never fetched, so what to do with the document is the caller's decision.
Null covers both an index of zero, which says the terms are not stated in the identifier, and an index added to the table after this package was released, which it cannot name. A caller cannot tell those two apart, which is deliberate, because both lead to the same place, being that the identifier does not say which terms it was created under and the answer has to come from somewhere else. No address is ever built from an index, since that would name a document nobody wrote.
No address does not mean the identifier is unrestricted. Where an identifier may go is a separate question the usage answers.
◆ getUsage()
| fiftyone\pipeline\did\FodId::getUsage | ( | ) |
The usage carried in bits 0-2 of the flags byte, as the highest usage granted.
See {
- See also
- Usage} for why it is read that way.
◆ isUsageIndirect()
| fiftyone\pipeline\did\FodId::isUsageIndirect | ( | ) |
Whether the usage is indirect, being worked out by the issuer from a signal other than the caller stating it, rather than direct, being stated by the caller.
Bit 3 of the flags byte.
A consent string is the only indirect signal today, so today this is true only when the usage was derived from one. The bit records direct against indirect rather than consent strings as such, so a later signal of another kind sets it too. Both are legitimate ways to arrive at a usage, and this says nothing about which usage it is.
◆ signatureStatus()
| fiftyone\pipeline\did\FodId::signatureStatus | ( | string | $publicPem | ) |
Says whether the signature is genuine for the public key given, and where the question could not be answered, says that instead of reporting a forgery.
{
- See also
- SignatureStatus::SignatureInvalid} is the only answer that means the identifier should be distrusted, and a key that cannot be read is {
- SignatureStatus::InvalidKey}.
◆ toStandardBase64()
|
static |
Restores a string in either base64 alphabet to the standard alphabet with padding.
Leading and trailing whitespace is removed first, since a value read from a header, a file or a form often carries a newline and the padding has to be counted from the characters that remain. Then - becomes +, _ becomes /, and == or = is added when the length modulo 4 is 2 or 3. A string already in the standard padded form is returned unchanged.
◆ tryFromBase64()
|
static |
Reads a 51Did from its base64-encoded OWID string, answering rather than raising when the value is not one.
The value may be anything at all, because it is external data, so a null, an empty string or a value of another type (for example the array PHP builds when a query string repeats a parameter with brackets) is reported by status rather than raised. A string in either alphabet is accepted, standard (+ and /, as the cloud issues it) or URL-safe (- and _, as a page puts it in a link), with or without padding, and surrounding whitespace is removed, as the cloud's endpoints normalise the alphabet and the padding.
The result carries the OWID library's own status when the envelope could not be read, and a {
- See also
- FodIdParseStatus} when the envelope was sound and the payload does not fit a 51Did. Success says nothing about the signature.
- Parameters
-
mixed $value the base64 text, or anything a caller was handed
◆ tryFromByteArray()
|
static |
Reads a 51Did from the raw bytes of an OWID envelope, answering rather than raising when the bytes are not one.
The buffer must be one whole envelope and nothing else. The statuses are those of {
- See also
- FodId::tryFromBase64()} less the base64 one.
- Parameters
-
mixed $buffer the raw bytes, or anything a caller was handed
◆ tryFromOwid()
|
static |
Reads a 51Did from an already-read {.
- See also
- Owid}, answering with a {
- FodIdParseStatus} rather than raising when the payload does not fit.
◆ verify()
| fiftyone\pipeline\did\FodId::verify | ( | string | $publicPem | ) |
Verifies the OWID signature against the supplied public key.
This is an explicit, separate step, as reading never verifies. False means the signature does not match this key, and a key that cannot be read is raised rather than reported as a mismatch. Where the difference between the two changes what the caller does, use {
- See also
- FodId::signatureStatus()}.
- Exceptions
-
OwidException when the PEM is not a valid public key.
