Signature Validation
The Identity Profile Report JSON contains a proof
object that can be used to verify the integrity of the data. To keep the JSON structure in human-readable form, we use a variation of JSON Web Signature (JWS) with detached payload format. This means that instead of carrying the JSON payload in the JWS, it can be attached to the payload as the proof.jws
field value, while keeping the payload as it was signed.
Below is the proof object structure:
"proof": {
"jws": "<encoded_signature>",
"public_key_url": "<url_for_public_key>"
}
Verification process
Verifying the signature and data integrity can be achieved by the following:
- Retain the
proof.jws
value from the Identity Profile Report. - Change the
proof.jws
value to an empty string (““) in the Report JSON. - Canonicalise the report according to RFC 8785.
- Verify the signature against the key that’s obtained by resolving
proof.public_key_url
.
Example code
x
const fs = require('fs');
const axios = require('axios');
const jose = require('jose');
const { canonicalize } = require('json-canonicalize');
// Load the JSON data from the file
const report = JSON.parse(fs.readFileSync('identity_profile_report.json', 'utf8'));
// Extract the proof.jws value and the proof.public_key_url
const jwsToken = report.proof.jws;
const publicKeyUrl = report.proof.public_key_url;
// Set the proof.jws value to an empty string
report.proof.jws = "";
// Canonicalize the JSON data according to RFC 8785
const canonicalizedReport = canonicalize(report);
// Base64url encode the canonicalized JSON data
const encodedPayload = Buffer.from(canonicalizedReport, 'utf8').toString('base64url');
// Decode the JWS token
const [protectedHeader, , signature] = jwsToken.split('.');
// Fetch the public key from the proof.public_key_url
axios.get(publicKeyUrl)
.then(async response => {
const publicKeyJwk = response.data.keys[0];
// Import the public key using jose.importJWK
const key = await jose.importJWK(publicKeyJwk, 'EdDSA');
// Construct the JWS object
const jws = {
protected: protectedHeader,
payload: encodedPayload,
signature: signature
};
// Verify the JWS signature using the flattenedVerify method
try {
await jose.flattenedVerify(jws, key, {
algorithms: ['EdDSA']
});
console.log("Signature is valid.");
} catch (err) {
console.error("Signature verification failed:", err);
}
})
.catch(err => {
console.error("Failed to fetch public key:", err);
});
Reference
- JWS Detached Payload - https://tools.ietf.org/html/rfc7515#appendix-F
- RFC 8785: JSON Canonicalization Scheme (JCS) - https://datatracker.ietf.org/doc/html/rfc8785
- RFC 7517: JSON Web Key (JWK) - https://datatracker.ietf.org/doc/html/rfc7517
Was this page helpful?