Metadata Signature Creation
To ensure the declaration is verifiable, all metadata must be signed using a private key, which generates a cryptographic signature proving its authenticity. Liccium supports two approaches for signing: X.509 Certificate-based signing and Keypair-based signing with embedded credentials.
Overview
Metadata signatures in Liccium serve multiple purposes:
- Authentication: Proves the identity of the declarer
- Integrity: Ensures the metadata hasn't been tampered with
- Non-repudiation: Provides proof that the declaration was made by the certificate holder
Two Signing Approaches
Approach 1: X.509 Certificate
- ✓ Uses X.509 certificate chain
- ✓ Certificate embedded in JWT header (x5c)
- ✓ Requires certificate authority validation
- ✓ Best for enterprise/organizational use
Approach 2: Generated Keypair
- ✓ Uses self-generated EC keypair
- ✓ Public key embedded as JWK in JWT header
- ✓ Credentials included in publicMetadata
- ✓ Best for flexible, self-managed identities
Prerequisites
Before creating signatures, ensure you have:
Required Components
- ✓ EC (P-256) private key
- ✓ Node.js environment
- ✓ Structured public metadata
- ✓ Verifiable credentials (for keypair approach)
Setup Requirements
- ✓ JWT signing library (jsonwebtoken)
- ✓ Crypto module for key operations
- ✓ Valid declarerId (DID format)
- ✓ Complete metadata structure
Approach 1: X.509 Certificate-Based Signing
This approach uses X.509 certificates to establish identity. The certificate chain is embedded in the JWT header using the x5c field.
Step 1: Prepare Your Public Metadata
Structure your public metadata according to Liccium requirements:
Code
Metadata Requirements: Ensure your metadata includes all required fields: $schema, @context, iscc, name, timestamp, declarerId, and credentials. Missing required fields will cause signature validation to fail.
Step 2: Load Your Certificate
Load your X.509 certificate and private key:
Code
Step 3: Create the JWT Signature
Generate a JWT signature using your certificate and private key:
Code
Step 4: Complete Certificate-Based Example
Full example with validation:
Code
Approach 2: Keypair-Based Signing with Embedded JWK
This approach uses a self-generated EC keypair. The public key is embedded in the JWT header as a JSON Web Key (JWK), and verifiable credentials are included in the publicMetadata.
Step 1: Generate an EC Keypair
Code
Step 2: Convert Public Key to JWK
Code
Step 3: Create JWT Signature with JWK in Header
Code
Step 5: Complete Keypair-Based Example
Code
Signature Verification
Decode the JWT (without verification) to inspect structure:
Code
Certificate-based (x5c): header contains x5c with base64-encoded certificate.
Keypair-based (jwk): header contains jwk with EC P-256 public key.
Security Best Practices
Security Considerations:
- Never log or expose private keys
- Use secure key storage in production (HSM, key vaults)
- Implement proper error handling for signing failures
- Validate all input data before signing
- Store credentials securely and validate before inclusion
Key Management
- Secure Storage – Store private keys in HSM or key vaults
- Access Control – Limit access to private keys to authorized systems
- Key Rotation – Regularly rotate keys/certificates and update DID documents
- Monitoring – Monitor key usage and detect unauthorized signing
Common Issues and Solutions
| Issue | Cause | Solution |
|---|---|---|
| Invalid signature format | Incorrect algorithm or header | Use ES256 and proper x5c or jwk header |
| Certificate/JWK not found | Missing x5c or jwk in JWT header | Include base64 certificate or JWK in header |
| Validation fails | Metadata missing required fields | Validate structure before signing ($schema, @context, iscc, name, timestamp, declarerId, credentials) |
| Key mismatch | Private key doesn't match certificate/public key | Verify key pair correspondence |
| Credentials validation fails | Missing or invalid credentials array | Ensure credentials is a non-empty array with valid VC structure |
Integration with Liccium
Include your signature in the declaration payload:
Code
For complete declaration examples, see the Declaration API.
Next Steps
- TSA Signature Creation – Add timestamp signatures for temporal verification
- Test your signatures with the Declaration API
- Implement error handling for production use
- Monitor certificate/key expiration and plan for renewal