@gaia-x/json-web-signature-2020
v2.3.0
Published
A lightweight JsonWebSignature2020 signing and verification Typescript library by Gaia-X AISBL
Downloads
1,028
Readme
Gaia-X JSON Web Signature 2020
🪶 A lightweight JsonWebSignature2020 signing and verification Typescript library by Gaia-X AISBL
Requirements
This library is designed to be compatible with Node version 18+.
The main requirements to run this library are to have a Typescript enabled project and an execution environment connected to the Internet to be able to resolve DIDs.
Getting Started
All you need to do is install this package.
npm install @gaia-x/json-web-signature-2020
You can then check out our examples below to get started signing and verifying verifiable credentials.
Currently Supported
DID Types
This library is mainly orientated towards Gaia-X verifiable credentials which are only based on did:web
at the moment
so other DID types are not supported.
| DID Type | Supported | |----------|:---------:| | did:web | ✅ | | did:key | ❌ | | did:ethr | ❌ | | did:jwk | ❌ | | did:btcr | ❌ | | did:dns | ❌ | | did:ebsi | ❌ | | ... | ❌ |
ℹ️ Please note that other DID resolvers can easily be integrated in this project as it is based on did-resolver which offers a plug-and-play driver approach.
Key Algorithms
This library supports all the algorithms supported by jose as it is used to import public & private keys. Please refer to jose's implemented specifications chapter to have more details.
| Algorithm | Supported |
|-----------|:---------:|
| HS256 | ✅ |
| HS384 | ✅ |
| HS512 | ✅ |
| PS256 | ✅ |
| PS384 | ✅ |
| PS512 | ✅ |
| RS256 | ✅ |
| RS384 | ✅ |
| RS512 | ✅ |
| ES256 | ✅ |
| ES256K | ✅ |
| ES384 | ✅ |
| ES512 | ✅ |
| EdDSA | ✅ |
Public Key Formats
Public keys are used for verifying verifiable credential proofs and are resolved via the verification method DID, the following public key formats are supported when collected from a DID document.
| Format | Supported | |-----------|:---------:| | JWK | ✅ | | Multibase | ❌ |
Create a Verifiable Credential
A verifiable credential is created by signing a document with a private key, this process creates a proof
attribute
for the verifiable credential with a jws
attribute containing the signature. This avoids tampering with the verifiable
credential after it has been signed.
JSON Web Signature 2020
To sign a document (hence making it a verifiable credential) with the JSON Web Signature 2020 specification, the
JsonWebSignature2020Signer
can be used in the following manner.
const document: Omit<VerifiableCredential, 'proof'> = { ... }
const signer: Signer = new JsonWebSignature2020Signer({
privateKey: await jose.importPKCS8(privateKeyPem, privateKeyAlgorithm),
privateKeyAlgorithm: 'ES256',
verificationMethod: 'did:web:my-domain.com#key-1'
})
const verifiableCredential: VerifiableCredential = await signer.sign(document)
👇 Please see the below Verification Methode chapter for more details about the
verificationMethod
argument.
Gaia-X JSON Web Signature 2020
The same method can be used with the GaiaXSignatureSigner
const document: Omit<VerifiableCredential, 'proof'> = { ... }
const signer: Signer = new GaiaXSignatureSigner({
privateKey: await jose.importPKCS8(privateKeyPem, privateKeyAlgorithm),
privateKeyAlgorithm: 'ES256',
verificationMethod: 'did:web:my-domain.com#key-1'
})
const verifiableCredential: VerifiableCredential = await signer.sign(document)
👇 Please see the below Verification Methode chapter for more details about the
verificationMethod
argument.
Verification Method
The verificationMethod
argument in the above examples corresponds to the verifiable credential's
proof.verificationMethod
attribute. This attribute is built by concatenating the DID and the public key ID with a
#
separating them.
Verify a Verifiable Credential
Verifiers
All verifiable credential verification is done through what we call a Verifier
, it is in charge of coordinating all
the steps and components necessary to that verification.
sequenceDiagram
participant S as Software
participant V as Verifier
participant R as DID Resolver
participant H as Hasher
S->>+V: Call verify() with Verifiable Credential
break when Verifiable Credential is malformed
V-->>S: Raise an Exception
end
V->>V: Separate Proof & Document
V->>V: Extract DID
V->>+R: Send DID
break when DID is not resolvable
R-->>S: Raise an Exception
end
R->>R: Resolve DID to Collect DID Document
R->>-V: Return DID Document
V->>V: Extract Public Key from DID Document
V->>+H: Send Document & Proof
H->>H: Canonize/Normalize JSON-LD
break when normalization fails
H-->>S: Raise an Exception
end
H->>H: SHA-256 Hashed Normalized Data
H->>-V: Return a Hash
V->>V: Verify the Proof's JWS
break when the proof verification fails
V-->>S: Raise an Exception
end
V->>-S: Void
👀 Don't hesitate to check out the
*.spec.ts
test files to find some real life examples of the usage of verifiers.
JSON Web Signature 2020
To verify a JSON Web Signature 2020 signed verifiable credential, you will need to instantiate the JsonWebSignature2020Verifier
class which packs all the necessary logic to validate it using the proof attribute.
const verifier: Verifier = new JsonWebSignature2020Verifier()
try {
await verifier.verify(verifiableCredential)
} catch (e) {
// Manage the verification exception
}
Gaia-X JSON Web Signature 2020
Just like the previous chapter, Gaia-x JSON Web Signature 2020 can be verified with the GaiaXSignatureVerifier
class.
const verifier: Verifier = new GaiaXSignatureVerifier()
try {
await verifier.verify(verifiableCredential)
} catch (e) {
// Manage the verification exception
}
Overriding with Options
Developers using this library will have different goals and needs depending on their application. To fit those needs, options have been introduced to be able to tweak the library's behaviour.
Using Options
Each component of this library can be tweaked with its own Options
object :
Hasher
uses the baseOptions
classSigner
uses theSignerOptions
class which extendsOptions
Verifier
uses theVerifierOptions
class which extendsOptions
// Hasher
const hasherOptions: Options = {
documentLoader: myDocumentLoader,
safe: false
}
const hasher: Hasher = new JsonWebSignature2020Hasher(hasherOptions)
// Signer
const signerOptions: Options = {
privateKey: myPrivateKey,
privateKeyAlg: myPrivateKeyAlg,
verificationMethod: myVerificationMethod,
documentLoader: myDocumentLoader,
safe: false
}
const signer: Signer = new JsonWebSignature2020Signer(signerOptions)
// Verifier
const verifierOptions: Options = {
didResolver: myDidResolver,
documentLoader: myDocumentLoader,
safe: false
}
const verifier: Verifier = new JsonWebSignature2020Verifier(verifierOptions)
☝️ Don't hesitate to check out the option classes in the src/options/ folder to find out which attributes are available. Modern IDEs integrate attribute resolution and autocompletion which can help you navigate possibilities.
Custom DidResolver
If a developer needs to use other DID methods or a custom DID resolver, this can be done through the Verifier
's
constructor.
const didResolver: CustomDidResolver = new CustomDidResolver()
const verifier: Verifier = new JsonWebSignature2020Verifier({ didResolver })
Offline Contexts
In certain cases, like verifying many verifiable credentials per second, rate-limiting can cause issues with JSON-LD
context resolving. An OfflineDocumentLoaderBuilder
has been provided in this library to locally resolve given contexts, it
can easily be used by injecting it in the wanted Hasher
or Verifier
.
Custom contexts can be added to this document loader by calling the OfflineDocumentLoaderBuilder#addContext(string, any)
method with the context's URL and its content which can be imported from a JSON file.
For Verifiers
const offlineDocumentLoader: DocumentLoader = new OfflineDocumentLoaderBuilder().build()
const verifier: Verifier = new JsonWebSignature2020Verifier({ documentLoader: offlineDocumentLoader })
For Hashers
const offlineDocumentLoader: DocumentLoader = new OfflineDocumentLoaderBuilder().build()
const hasher: Verifier = new JsonWebSignature2020Hasher({ documentLoader: offlineDocumentLoader })
With Custom Contexts
import MyContext from 'contexts/my-context.json'
import CustomContext from 'contexts/custom-context.json'
const offlineDocumentLoader: DocumentLoader = new OfflineDocumentLoaderBuilder()
.addContext('https://my-context.org/2024/entities/v1', MyContext)
.addContext('https://custom-context.org/2024/entities/v1', CustomContext)
.build()
With cached Contexts
const offlineDocumentLoader: DocumentLoader = new OfflineDocumentLoaderBuilder()
.addCachedContext('https://my-context.org/2024/entities/v1')
.build()
Cached contexts are fetched only every 10 minutes to avoid rate limiting.
🔍 Make sure you have
"resolveJsonModule": true
is yourtsconfig.json
configuration file in order to be able to import the contexts from JSON files.
Utilities
As this library needs to work on multiple aspects of verifiable credentials and JSON-LD in general, some utility classes are made available for developers.
Context Handler
The ContextHandler
class allows developers to manipulate JSON-LD contexts with ease, please see
the class' JSDoc for more details.
import { ArrayContext } from './jsonld.types'
const context: ArrayContext = ContextHandler.fromContext(context)
.add('https://www.w3.org/ns/odrl.jsonld')
.add('https://w3id.org/security/suites/jws-2020/v1')
.toContext()
verifiableCredential['@context'] = context
⚠️ Aliased contexts are not managed at the moment as JSON-LD expansion/compaction issues arise. Only contexts in the form of arrays are supported.