HomeAge Verification HeadlessAI Services for TerminalsAge Estimation VerifySupportTrust APIIdentity Verification LivenessDigital IDIdentity verificationDigital ID MigrationDBS RTWDigital IDDBS/RTW portaleSignaturesAge verificationAge estimationIn-Branch VerificationAge Estimation v2idv-portal-errorsIdentity ProfilesVerifiable Credentialssandbox-betaIdentity Verification APIAI Services APITrust APIProof of Age (PoA) API
DBS RTW
v9.0
Digital ID Integration guide
Embedded IDV Integration Guide
Title
Message
Create new category
What is the title of your new category?
Edit page index title
What is the title of the page index?
Edit category
What is the new title of your category?
Edit link
What is the new title and URL of your link?
Signature Validation
AI Tools
Summarize Page
Copy Markdown
Open in ChatGPT
Open in Claude
Connect to Cursor
Connect to VS Code
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:
JSON
"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.jwsvalue from the Identity Profile Report. - Change the
proof.jwsvalue 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
Node.js
Python
Go
PHP
Java
C#
x
const fs = require('fs');const axios = require('axios');const jose = require('jose');const { canonicalize } = require('json-canonicalize');// Load the JSON data from the fileconst report = JSON.parse(fs.readFileSync('identity_profile_report.json', 'utf8'));// Extract the proof.jws value and the proof.public_key_urlconst jwsToken = report.proof.jws;const publicKeyUrl = report.proof.public_key_url;// Set the proof.jws value to an empty stringreport.proof.jws = "";// Canonicalize the JSON data according to RFC 8785const canonicalizedReport = canonicalize(report);// Base64url encode the canonicalized JSON dataconst encodedPayload = Buffer.from(canonicalizedReport, 'utf8').toString('base64url');// Decode the JWS tokenconst [protectedHeader, , signature] = jwsToken.split('.');// Fetch the public key from the proof.public_key_urlaxios.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
Type to search, ESC to discard
Type to search, ESC to discard
Type to search, ESC to discard
Last updated on
Was this page helpful?
Next to read:
Error responsesGot a question? Contact us here.
Discard Changes
Do you want to discard your current changes and overwrite with the template?
Archive Synced Block
Message
Create new Template
What is this template's title?
Delete Template
Message