Louis Holbrook and I have been working with Dodji Honou of h-fablab to develop a case study example with a flexible structure for certifications under the People and Skills (PSS) initiative.
Repo of this work: git clone -b “lash/rdf-propose” git://holbrook.no/iop/tools.git
The motivation is to make the core requirements as small as possible, and allow certifying entities great liberty in choosing and defining vocabularies to represent the components of the certifications.
Data format
These examples are illustrated in the rdf-turtle
data format, in short a human-readable expression of the RDF standard.
Intuition about RDF
A simplified explanation of RDF is to express how something (subject) relates (predicate) to something else (object).
Such a relation is named a “triple,” and each part of the triple references a Uniform Resource Identifier (URI).
Compatibility with PSS
This use-case only concerns itself with the data of the subject to be certified.
The current PSS specification is provided as a JSON schema.
A separate document is provided to advise a migration to RDF, which will also touch on current issues with schema conformance and constraints.
The following will assume such a migration.
Badges
The portion of the specification that relates to badges are not treated here. In this context they are considered artifacts that can be dynamically created from the actual certificate date.
Although there is case for including assets (e.g. images, templates) and algorithms (e.g. data transformations, mappings) within the structure to regenerate complete badge assets, this is out of scope for this initial use-case.
Contents
The following will describe each conception section of contents in the example.
Prefixes
The document starts with a list of prefixes. In the turtle format, these define aliases used in the rest of the document as placeholders for longer (URI) names.
An example;
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
<http://holbrook.no>
foaf:name "Louis Holbrook"^^xsd:String .
In this case foaf
is expanded when generating RDF triples, and the result becomes:
<http://holbrook.no> <http://xmlns.com/foaf/0.1/name> "Louis Holbrook^^<http://www.w3.org/2001/XMLSchema#String>" .
What does this mean, in practice?
The answer is that it depends on the client who is reading the data. But the naïve interpretation could be:
“There is a way to assign a name to the site holbrook.no, and the name is the following sequence of letters: …”
Example prefixes
The prefixes used in this example represent a wide variety of different vocabularies. The can roughly be grouped into four categories:
- well-known, location specific intended for RDF (e.g.
xsd
,foaf
,dc
…). - well-known, location specifick, not intended for RDF (e.g.
iso3316a2
). - well-known, location independent (e.g.
sha256
,uuid
) - lesser-known, unknown, or does not yet concretely exist (
hfl*
,pss*
,df
)
Prefixes used in this example
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix sha256: <URN:sha256:> .
@prefix uuid: <URN:uuid:> .
@prefix prov: <https://www.w3.org/TR/2013/REC-prov-o-20130430/#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix mime: <http://www.iana.org/assignments/media-types/> .
@prefix wot: <http://xmlns.com/wot/0.1/>.
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix df: <http://defalsify.org/rdf/0.1/core/> .
@prefix hflt: <http://h-fablab.org/rdf/terms#> .
@prefix hflc: <http://h-fablab.org/rdf/courses/> .
@prefix hfl: <http://h-fablab.org/rdf/core#> .
@prefix pss: <https://standards.internetofproduction.org/pub/r7g0n9fo/release/4> .
@prefix psst: <https://standards.internetofproduction.org/pub/r7g0n9fo/release/terms#> .
@prefix pssy: <https://standards.internetofproduction.org/pub/r7g0n9fo/release/terms#> .
@prefix iso3316a2: <https://www.iso.org/obp/ui/#iso:code:3166:> .
Certificate entry point
This is the root node of the ceriticate.
It references:
subject
- who is being certifiedobject
- what is the subject being certified foragent
- In this example, who hosted the course
Note that each of these predicates are expressed in a vocabulary under a hlfc
prefix.
# the certificate parameters issued by the makerspace
uuid:6f93d1e2-2d7d-4648-a96f-3a0fbd9f3693
hflc:subject uuid:ba52c94f-a9c3-4e55-a103-1bc46b1608df ;
hflc:object uuid:a22292c6-0954-42ef-b1ac-b21476972cd6 ;
hflc:agent uuid:f5191421-24ee-4d37-b460-c3208e3e7ea9 .
Course unit
The contents here are taken from an example provided from h-fablab.org.
Notice the value hflc:courseReport
which references a sha256 digest (also called a “sha256 hash”).
At the moment of writing, any sha256:<digest>
resources have been made available on this URL:
https://g33k.holbrook.no/<digest>
You can assert the contents of the file provided by calculating your own digest, e.g. using the e.g. sha256sum
command line tool, or online resources such as https://devtool.online/digest/sha256.
At this point, also note that it does not matter what source the file comes from. It could be your file system or a USB stick. You can calculate the digest, and if it’s exactly the same, then it is exactly the same file.
Categorization
Notice also how different vocabularies can be used within the same subject reference to express the same thing in different ways.
# a description of the skill/course unit being certified
uuid:a22292c6-0954-42ef-b1ac-b21476972cd6
dc:title "Rapport de formation modélisation et impression 3D au Lycée Technique d'Abidjan" ;
prov:startedAtTime "2022-02-15T07:00:00Z"^^xsd:DateTime ;
prov:endedAtTime "2022-02-17T14:00:00Z"^^xsd:DateTime ;
hflc:courseReport sha256:224534ab7f095ef9b135155ca7172491350730977f23b9a84e1cbfce8b51f926 ;
hfl:category hflt:3Dprint ;
hfl:category hflt:3Dmodel ;
pss:topic psst:3D ;
a hfl:Unit .
Course agent
In this case we limit ourselves to one agent, which is the physical and legal host of the workshop that carried out the course described.
The number of agents involved could be much more granularized. But it is also important that the structure works when minimal data is available.
This example is not even the absolute minimum (a minimum could e.g. simply be a web URL), but does demonstrate at least some level of simplicity.
# one of the agents, in this case the legal and physical host of the course being certified
uuid:f5191421-24ee-4d37-b460-c3208e3e7ea9
foaf:name "Lycée Technique d'Abidjan" ;
foaf:homepage <https://lta-ci.net/> ;
a foaf:Organization .
The certificate subject
This part of the document is an adaptation of the People and Skills subject data object.
It is a combination of different vocabularies; well-known ones where common concepts are used, and less well-knowns that assist data fields that are less supported by the RDF ecosystem.
Compatibility
It is not compatible with the current PSS standard proposal (version 4). Please refer to the supporting doucment proposing a modified approach to the standard:
https://g33k.holbrook.no/a2ef19b045fa37a0058e3ab19afa4214b5e7997ba4c35c37101a3a00967c7bf9
# the iop-pss standard layer
# pss person INHERITS many different vocabularies
uuid:ba52c94f-a9c3-4e55-a103-1bc46b1608df
dct:created "2023-03-27T12:34:56+00:00"^^xsd:dateTime ;
foaf:GivenName "Sarah" ;
foaf:FamilyName "Hutton" ;
foaf:name "Sarah Hutton" ;
psst:nationality iso3316a2:US ;
psst:residenceCountry iso3316a2:US ;
df:hasIdentity uuid:362b6e8c-cead-473a-8c0f-1b6197a90a84 ;
wot:hasKey uuid:80aecb88-04c7-4587-92c1-e3ac9f24d992 ;
a pss:Person .
Subject key
This defines the PGP key of the certificate subject, defined in the previous section.
You will notice the uuid:
reference in the object of wot:hasKey
that matches the subject in this record.
The wot:fingerprint is a reference to a particular packaging of behalf of a user’s key, and not an unambiguous reference to the key itself. Keep in mind that there are other ways to create this reference, that are less anchored to the PGP infrastructure.
# a key representing the subject
uuid:80aecb88-04c7-4587-92c1-e3ac9f24d992
wot:fingerprint "C0036D11C5386757A45242B471AB077CA401983F" ;
a wot:pubKey .
Certificate testimonials - witnesses
This section binds together the “witnessing” of the participation of a “subject,” defined as the person with a key in previous two sections, with the “course” defined in the two sections before that.
The witnessing entity expresses these data fields themselves, which also means that they cryptographically sign these entries themselves.
Note how this testimony is defined for a specific course (df:testifies
).
The predicates are assumed to be self-explanatory. But some details warrant further scrutiny:
Choosing identity
The hasIdentity
fields here points to a did resource. This is not a prefix in this document, it is a URI scheme meant to be interpreted in a specific way.
How did
works is out of scope for this document.
The use of it here is meant to contrast how the subject was identified previously (with a wot:hasKey
predicate).
Important is to keep in mind that it could just as well have been the other way around; the witness could have been identified by a direct reference to a PGP key, and the subject could be using a did
. Or both could make use of both schemes, even in the same document. This is the beauty of the flexibility of the RDF standard, it is specifically designed for such flexibility.
Representation
The prov:actedOnBehalfOf
predicate lets the witness claim to be operating on behalf of any number of institution in the context of the testimony.
It is worth to consider that saying it doesn’t necessarily make it so; even if the witness signs off on those claims, it’s still only the witness’ claims that such representation legitimately could take place.
And most importantly; it is up to whoever ingests this certificate to judge whether the witness’ claim of representation is valid by itself, or if it warrants further confirmation, e.g:
- a second signature (quorum)
- a higher-up signature (hierarchy)
- etc…
# testimonial metadata
uuid:dac71fa1-e3e0-44c4-b0d8-25f2b7571f88
df:perceivedTime "2023-03-05T19:04:40+00:00"^^xsd:dateTime ;
df:perceivedThrough df:inPerson ;
df:verdict df:certfied ;
df:hasClaim uuid:7d7e7931-a7f3-448b-b215-b67bb34e2da3 ;
df:hasIdentity <did:example:123456789abcdefghi> ;
# valid, but weak, provenance, as in the future may have to investigate to determine the organization
prov:actedOnBehalfOf <http://internetofproduction.org> ;
# valid, stronger, because it cites a structured document
prov:actedOnBehalfOf uuid:f5191421-24ee-4d37-b460-c3208e3e7ea9 ;
# valid, stronger, because it cites a content addressed resource
prov:actedOnBehalfOf sha256:e699432a6ebe93dfd483fa074db624810fe877bfd12c6bd32c43433323e5eace ;
df:testimonyFor uuid:6f93d1e2-2d7d-4648-a96f-3a0fbd9f3693 ;
a df:Testimony .
Testimony signature
The signature is made over the testimony object.
Note how if this content is included in a document, it will be merged with the same subject.
To re-create the data, it must be sufficient simply to remove the signature and calculate the hash of the remaining fields.
# testimonial signature
uuid:dac71fa1-e3e0-44c4-b0d8-25f2b7571f88
df:signature sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2 .
Testimonial asset
Notice how, in the previous section, there a field hasClaim
referenced another resource.
This is the resource it referenced.
This describes a media asset that is meant to reinforce the witness claim.
And in this example, this is a video file, where we can imagine that the witness personally records a statement re-iterating some or all or some and more of the details in these claims.
The sum
field here references the asset data, which, as in previous examples involving digests, detaches the data storage requirement from the cryptographically secured testimony itself.
# testimonial asset
uuid:7d7e7931-a7f3-448b-b215-b67bb34e2da3
dct:title "Testimonial" ;
dct:description "A video of personal testimony comment" ;
dct:created "2024-03-05T19:04:40+00:00"^^xsd:dateTime ;
dc:format mime:video\/mp4 ;
dc:type dct:MovingImage ;
dc:language "en" ;
df:sum sha256:dcd9f7154fd3ac19d03676ed6f786fbbaac5b7cee31d311bafb7fb84113025bf ;
a df:attachmentData .
Identity asset
This is provided to illustrate how the same construct used for a witness media asset can be used to reference a document that backs up a claim of identity.
In this case, we go all the way back to the field df:hasIdentity
of the The certificate subject section above. As you see, if matches the uuid:
subject of this record.
The implication of having two “claims” of identity is:
- You believe that anyone who signed this media file decided, one way or another, to testify that this person maps to the identity document and the image.
- The testification works for the key in the same way.
# identity asset
uuid:362b6e8c-cead-473a-8c0f-1b6197a90a84
dct:title "National identity card" ;
dct:description "Selfie photo of subject holding national identity card" ;
dct:created "2024-04-05T19:04:40+00:00"^^xsd:dateTime ;
dc:format mime:image\/png ;
dc:type dct:StillImage ;
df:sum sha256:f268f97b99be0e2d99a239711458edf2fb47455f397d0cf7f1f05cee84235ce8 ;
a df:attachmentData .
Signature
As we have seen, the cryptographic signature agent in this case is the witness.
A witness signs an association defined in a df:Testimony
.
In this model, any number of “witnesses” may do the same for any type of object. And it is up to the consumer of these structures to calculate what this means. Some thoughts:
- How much trust is granted to each signatory
- What trust is granted to a signatory for a specific predicate or object
- What weight does each signature have in each context
There is a huge potential for complexity in such interpretations. The most important feature of any standard is that it allows for complexity but does not demand it.
Portable signature format
The project should include a tool to export the signature(s) of the certificate to a portable, self-documented format.
For this, I will propose the AdES specification.
This is a variant of the XadES standard, which in turn is a derivative of xml dsig 1.1, i.e. largely an adherence to USA imperial standards.
The standard is chosen because it seems that a lot of EU money is flowing into their respective countries’ ex-colonial territories, and it would make sense to harmonize with their purported standards opportunities.
(TODO: the example below is copy and pasted from a different project, and does not reflect any values from the above)
<?xml version="1.0"?>
<Signature Id="sig-a0f819f9-6813-4f14-a7c8-f33c12f0c846" xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
<Reference URI="sha256:c370ef38855e38da02ae29888ee0365ed3d71465e6a7735ac7e7da5c1013e744">
<Transforms>
<!--<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>-->
<Transform Algorithm="https://csrc.nist.gov/glossary/term/sha_256" />
<Transform Algorithm="https://eips.ethereum.org/EIPS/eip-191#version-0x45-e" />
</Transforms>
<DigestMethod Algorithm="https://csrc.nist.gov/glossary/term/sha_256" />
<DigestValue>w3DvOIVeONoCrimIjuA2XtPXFGXmp3Nax+faXBAT50Q=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>u6jZ7fQiy59d/gfwGXwgnObcls0lLE0l8zEt/isQZA1jhlgqaMT9i4KQSFnpMrGlAMpDoL8UyYXZUoQB7RJlOQA=</SignatureValue>
<KeyInfo>
<KeyName>eb3907ecad74a0013c259d5874ae7f22dcbcc95c</KeyName>
<ECKeyValue xmlns="http://www.w3.org/2009/xmldsig11">
<PublicKey>BJ9rtqfj9bfucXVqiRIz0UFWWPhxK6x0AoLgg9ySQPU2i9s7JWpb9AqPf5dTQUy0R+4/eWxfMPfrQKf1AY/H8C4=</PublicKey>
<ECParameters>
<FieldID>
<Prime>
<P>/////////////////////////////////////v///C8=</P>
</Prime>
</FieldID>
<Curve>
<A>AA==</A>
<B>Bw==</B>
</Curve>
<Base>BHm+Zn753LusVaBilc6HCwcCm/zbLc4o2VnygVsW+BeYSDradyajxGVdpPv8DhEIqP0XtEimhVQZnEfQj/sQ1Lg=</Base>
<Order>/////////////////////rqu3OavSKA7v9JejNA2QUE=</Order>
<CoFactor>1</CoFactor>
</ECParameters>
</ECKeyValue>
</KeyInfo>
</Signature>