Skip to main content

Zero-knowledge auditing

When an audit needs to take place, the local JLINC Server retrieves audit records from the remote server which can be used to validate data provenance and integrity to ensure nothing has been modified in the system. We can retrieve audit records in multiple ways.

To retrieve all audit records for a given agreement:

const checkAgreementAudit = (await axios.post(
`https://api-test.jlinc.io/api/v1/audit/get`,
{
agreementId: agreement.created.agreementId,
},
{
headers: {
'Authorization': `Bearer ${archiveToken}`,
}
}
)).data;
console.log(`Agreement audits: ${JSON.stringify(checkAgreementAudit, null, 4)}\n`);

To retrieve all audit records for a given event:

const checkEventAudit = (await axios.post(
`https://api-test.jlinc.io/api/v1/audit/get`,
{
eventId: userEvent.created.eventId,
},
{
headers: {
'Authorization': `Bearer ${archiveToken}`,
}
}
)).data;
console.log(`Event audits: ${JSON.stringify(checkEventAudit, null, 4)}\n`);

To retrieve all audit records for a given internal identifier:

const checkEventAuditByMetaId = (await axios.post(
`https://api-test.jlinc.io/api/v1/audit/get`,
{
meta: {
myCustomId: 'my_custom_identifier', // Multiple specified keys respond with AND not OR
}
},
{
headers: {
'Authorization': `Bearer ${archiveToken}`,
}
}
)).data;
console.log(`Event audits by meta ID: ${JSON.stringify(checkEventAuditByMetaId, null, 4)}\n`);

Once these audit records have been retrieved, the local JLINC Server can be used to validate the data stored in the JLINC data store. In addition to the audit records, the verify call takes in the short names of any DIDs that signed the records. The local server can then retrieve the public keys for those entities to validate cryptographic signatures.

const validateAudit = (await axios.post(
`https://api-test.jlinc.io/api/v1/data/audit/verify`,
{
audits: [
...checkEventAudit.auditRecords,
...checkEventAuditByMetaId.auditRecords,
],
shortNames: [user.didDoc.shortName, provider.didDoc.shortName]
},
{
headers: {
'Authorization': `Bearer ${token}`,
}
}
)).data;
console.log(`Validation: ${JSON.stringify(validateAudit, null, 4)}\n`);

The above call will result in a response of valid or invalid records. An example of this return:

{
"valid": [
{
"audit": {
"audit": {
"version": 1,
"agreementId": "58810f16-b976-41f0-9566-2c26f174b592",
"hashType": "SHA256",
"digest": "246fd38f61e114f18d7a0137f409126b092b815f5849be615b6d27fb598bdc01",
"created": 1756998732778
},
"signatures": [
{
"version": 1,
"id": "did:jlinc:fedid-test.jlinc.io:Sd3iPCjfOoEYhu_Yea1OGTF3OFuvm17173WyEnqCZ6A",
"signedOn": 1756998732779,
"type": "JWS/JCS",
"jws": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImp3ayI6eyJrdHkiOiJPS1AiLCJjcnYiOiJFZDI1NTE5IiwieCI6IlI3eUdzSkl5NnNOVjRSTEhDYzJiTnRpeTBOS3hETzZVeHMtZUVXekR6eTAiLCJraWQiOiJkaWQ6amxpbmM6ZmVkaWQtdGVzdC5qbGluYy5pbzpTZDNpUENqZk9vRVlodV9ZZWExT0dURjNPRnV2bTE3MTczV3lFbnFDWjZBIn19.eyJhZ3JlZW1lbnRJZCI6IjU4ODEwZjE2LWI5NzYtNDFmMC05NTY2LTJjMjZmMTc0YjU5MiIsImNyZWF0ZWQiOjE3NTY5OTg3MzI3NzgsImRpZ2VzdCI6IjI0NmZkMzhmNjFlMTE0ZjE4ZDdhMDEzN2Y0MDkxMjZiMDkyYjgxNWY1ODQ5YmU2MTViNmQyN2ZiNTk4YmRjMDEiLCJoYXNoVHlwZSI6IlNIQTI1NiIsInZlcnNpb24iOjF9.ZmBIC3zEW-tO3KaYtjbs7XrPzo8UsU4LZiEKUUAjkUNFASUj2NKLth1vszH81pPOLkJG9bl8_f76vyrCcygbDg"
}
]
},
"results": {
"validId": true,
"validSignature": true,
"validAuditHash": true,
"validAuditSignature": true,
"validMatchingDids": true,
"validEventAgreement": true,
"validEventAgreementSignature": true
}
}
],
"invalid": []
}

The results from this includes multiple boolean variables, which can be interpreted as:

VariableDescription
validIdThe event ID in the local data store matches the event ID in the audit record.
validSignatureThe cryptographic signature on the data in the local data store is valid.
validAuditHashThe hash in the audit record is a valid representation of the data stored in the local data store.
validAuditSignatureThe cryptographic signature on the audit record is valid.
validMatchingDidsThe DIDs that signed the audit also signed the target object.
validEventAgreementIf the target object is an event, the DIDs that signed the audit signed the agreement governing the event.
validEventAgreementSignatureIf the target object is an event, the signatures on the agreement governing the event are valid.

If any one of these variables is false, the record is placed in the invalid array.