VCVerifier supports compliance verification for credentials that are part of a Gaia-X trust framework. This ensures that credentials meet regulatory and technical compliance requirements.
Overview
Compliance verification validates:
- Compliance credential presence: A separate compliance credential references the main credential
- Integrity signature: The hash of the main credential matches the compliance credential’s integrity claim
- Gaia-X subject type: The compliance credential contains the correct Gaia-X subject type
Source reference: verifier/compliance.go
How Gaia-X Compliance Works
In Gaia-X ecosystems, credentials are accompanied by compliance credentials issued by authorized compliance services.
Compliance Credential Structure
A Gaia-X compliance credential contains a credentialSubject with type gx:compliance:
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiableCredential", "GaiaXComplianceCredential"],
"issuer": "did:web:compliance.gaia-x.eu",
"credentialSubject": {
"type": "gx:compliance",
"id": "https://example.com/credentials/123",
"gx:integrity": "sha256-9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"gx:integrityNormalization": "RFC8785",
"gx:version": "1.0",
"gx:type": "LegalParticipant"
}
}
Compliance Subject Fields
Must be gx:compliance to indicate this is a compliance subject.
The identifier of the credential being attested. Must match the main credential’s ID.
SHA-256 hash of the canonicalized credential, prefixed with sha256-.
gx:integrityNormalization
Normalization method used (typically RFC8785 for JSON canonicalization).
Version of the Gaia-X compliance framework.
Type of Gaia-X credential being attested (e.g., LegalParticipant, ServiceOffering).
Configuration
Compliance verification is configured per credential type in the scope configuration:
configRepo:
services:
- id: myService
oidcScopes:
default:
credentials:
- type: LegalParticipantCredential
compliance:
required: true
Compliance verification is optional. Only credentials explicitly configured with compliance.required: true will be checked.
Verification Process
The verifier searches the presentation for compliance credentials:
for _, credential := range presentation.Credentials() {
subject := credential["credentialSubject"]
if subject["type"] == "gx:compliance" {
complianceSubjects = append(complianceSubjects, subject)
}
}
Step 2: Match Credential ID
For each credential requiring compliance, find a compliance subject with matching ID:
for _, complianceSubject := range complianceSubjects {
if complianceSubject.Id == credential.ID {
// Found matching compliance credential
}
}
Step 3: Verify Integrity Signature
The verifier canonicalizes the credential and computes its SHA-256 hash:
Source reference: verifier/compliance.go:52-64
func checkSignature(rawCredential []byte, signature string) (bool, error) {
// Canonicalize using RFC8785
canonicalized, _ := jsoncanonicalizer.Transform(rawCredential)
// Compute SHA-256 hash
hash := sha256.Sum256(canonicalized)
hashHex := "sha256-" + hex.EncodeToString(hash[:])
// Compare with compliance signature
return hashHex == signature, nil
}
Example Flow
1. Main Credential
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"id": "https://example.com/credentials/legal-participant-123",
"type": ["VerifiableCredential", "LegalParticipantCredential"],
"issuer": "did:web:example.com",
"credentialSubject": {
"id": "did:web:company.example.com",
"gx:legalName": "Example Corp",
"gx:legalForm": "LLC"
}
}
2. Compliance Credential
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiableCredential", "GaiaXComplianceCredential"],
"issuer": "did:web:compliance.gaia-x.eu",
"credentialSubject": {
"type": "gx:compliance",
"id": "https://example.com/credentials/legal-participant-123",
"gx:integrity": "sha256-abc123def456...",
"gx:integrityNormalization": "RFC8785",
"gx:type": "LegalParticipant"
}
}
3. Presentation
Both credentials must be included in the presentation:
{
"@context": ["https://www.w3.org/2018/credentials/v1"],
"type": ["VerifiablePresentation"],
"holder": "did:web:company.example.com",
"verifiableCredential": [
{/* Main credential */},
{/* Compliance credential */}
]
}
Gaia-X Registry Integration
VCVerifier can also validate issuers against the Gaia-X Digital Clearing House Registry.
Configuration
verifier:
policyConfig:
defaultPolicies:
GaiaXComplianceIssuer:
registryAddress: "https://registry.lab.gaia-x.eu"
Source reference: verifier/gaiax.go:27-48
Issuer Validation
The GaiaXRegistryValidationService checks if the issuer is in the trusted compliance issuers list:
func (v *GaiaXRegistryValidationService) ValidateVC(
credential *verifiable.Credential,
context ValidationContext,
) (bool, error) {
issuerDids, _ := v.gaiaxRegistryClient.GetComplianceIssuers()
if slices.Contains(issuerDids, credential.Issuer.ID) {
return true, nil
}
return false, ErrorNoTrustedIssuer
}
Credential-Specific Policies
Apply Gaia-X validation to specific credential types:
verifier:
policyConfig:
credentialTypeSpecificPolicies:
LegalParticipantCredential:
GaiaXComplianceIssuer:
registryAddress: "https://registry.lab.gaia-x.eu"
ServiceOfferingCredential:
GaiaXComplianceIssuer:
registryAddress: "https://registry.lab.gaia-x.eu"
Error Handling
No Compliance Credential Found
If compliance is required but no matching compliance credential exists:
{
"error": "invalid_vc",
"description": "No compliance subject found for credential"
}
Log output:
No compliance subject found for credential ID https://example.com/credentials/123
Integrity Mismatch
If the computed hash doesn’t match the compliance signature:
{
"error": "invalid_vc",
"description": "Credential integrity check failed"
}
Log output:
The created signature is sha256-abc123... - the signature to test sha256-def456...
Invalid Subject Type
If the subject type is not gx:compliance:
Was not able to convert context. Err: type assertion failed
Complete Configuration Example
verifier:
did: "did:web:verifier.example.com"
validationMode: "combined"
policyConfig:
defaultPolicies:
GaiaXComplianceIssuer:
registryAddress: "https://registry.lab.gaia-x.eu"
configRepo:
services:
- id: gaiax-marketplace
oidcScopes:
participant:
credentials:
- type: LegalParticipantCredential
compliance:
required: true
trustedIssuersLists:
LegalParticipantCredential:
- https://tir.gaia-x.eu
- type: ServiceOfferingCredential
compliance:
required: true
trustedIssuersLists:
ServiceOfferingCredential:
- https://tir.gaia-x.eu
Best Practices
-
Require compliance for sensitive credentials: Enable compliance verification for credentials with regulatory requirements
-
Use trusted compliance services: Only accept compliance credentials from authorized Gaia-X compliance services
-
Monitor compliance failures: Track compliance verification failures to identify credential issues early
-
Document compliance requirements: Clearly communicate compliance requirements to credential issuers
-
Keep registries updated: Regularly sync with the Gaia-X registry to maintain current trusted issuer lists
Security Considerations
Compliance verification does not replace cryptographic proof verification. Both are required for complete security:
- Proof verification: Ensures the credential hasn’t been tampered with
- Compliance verification: Ensures the credential meets regulatory requirements
Integrity Hash Security
The integrity hash provides:
- Tamper detection: Any modification to the credential changes the hash
- Attestation binding: Links the compliance credential to the specific credential version
- Non-repudiation: Compliance service’s signature proves their attestation
Canonicalization Importance
JSON canonicalization ensures:
- Consistent hashes regardless of formatting
- Field order doesn’t affect validation
- Whitespace differences don’t break verification