The ConsensasRSA2021 is based on W3C's Linked Data Proofs. The core difference is that ConsensasRSA2021 does not depend on Linked Data or JSON-LD, though fully compatible with it.
Canonical JSON is defined by RFC8785. It ensures that given any JSON message, we can create exactly the same representation.
See QCompacted. The proof SHOULD (maybe MUST?) be encoded using QName Compacted JSON-LD.
Javascript Object Signing and Encryption is used for JSON Web Signatures RFC 7515.
Also see Node.JS implementation.
- Have a Private Key, which is closely held
- Have a Public Key, which is published on the web as a URI, along with it's Certificate Chain. The Certificate Chain MUST be in the Leaf to Root order, There is no requirement for the Root and Intermediate(s) Certificates to be there, but the order most be correct.
- ensure "@context" contains
"security": "https://w3id.org/security#"
- remove
security:proof
from message - make a canonical version of message
- create proof without signature, e.g. containing
security:created
andsecurity:nonce
, plus all the other framing details. - make a canonical version of the proof
- sign canonical message "\n" canonical proof using JOSE JWS RS256
- detach the payload from the proof (the middle bit, between the "."s)
- add the signature to the proof
- detach proof from message
- detail JWS from proof
- using the signing algorithm, rebuild the canonical message and canonical proof
- using the
verificationMethod
, retrieve the Public Key PEM - rebuild the JWS and compare to the one that came in the proof
- ensure that Certificate Chain is valid, eg. the Public Key is signed by the Intermediate, and the Intermediate by the Root
security:type
- always "https://models.consensas.com/security#ConsensasRSA2021"security:proofPurpose
- alwaysassertionMessage
security:created
- a UTC ISO Timesecurity:nonce
- a randomly generated string, to prevent replayssecurity:verificationMethod
- the URI to get the Public Key
Certificate chain, in PEM format (consider allowing JSON serialization). The leaf key should be first, the CA/Root key last.security:jws
- the detached JWS signature, as computed by the algorthm
Here is an example of a signed message
{
"@context": {
"security": "https://w3id.org/security#"
},
"hello": "world",
"security:proof": {
"security:type": "https://models.consensas.com/security#ConsensasRSA2021",
"security:proofPurpose": "assertionMethod",
"security:created": "2021-01-20T13:03:45.450Z",
"security:nonce": "14182305723832145",
"security:verificationMethod": "https://example.org/public.cer.pem",
"security:jws": "eyJhbGciOiJSUzI1NiIsImtpZCI6Im5nc1FzdFVmMDlmTDhwTnRxZHk5V1ctX3BUM0R4TGpLYlF5ZGItR0xPN2cifQ..Np4accZ6rX8N5MFXCYZEaVral45DhGwp2WEsMbsxrIacirruNml8auArmImYo8M57m3cyl8tf8d5wXCwx-1KwijT_uvkAl-v8CBcQU_2CmpJ-WrKvMlcHMm21-LAnxn2bqWnsgWDHX2W2buwDZTIZTfXrAQBl-5Ofa43GccU3TXin5i6feLXc8VVRC89D5kP45kjltSnXdS6cD3ZCjCDJLFLaWb-khaxENK_LrADRm2Zt3r7x-dXsKaKLxtyjYzNg005g5Ws528V6xWfZs5OKOys1VdYLH-1iVApCUGoC6ijlSN2F9CpNrStbGRxrqg-3gTy6zwxp9DOkSp8H7SUtQ"
}
}
You can recreate this yourself:
cd information-passport/tools/bin
node sign.js \
--file ../data/hello.json \
--key ../data/private.key.pem \
--verifier "https://example.org/public.cer.pem"
Here is that message validated (normative format)
{
"proof": {
"type": "https://models.consensas.com/security#ConsensasRSA2021",
"proofPurpose": "assertionMethod",
"created": "2021-01-20T13:03:45.450Z",
"nonce": "14182305723832145",
"verificationMethod": "https://example.org/public.cer.pem",
"jws": "eyJhbGciOiJSUzI1NiIsImtpZCI6Im5nc1FzdFVmMDlmTDhwTnRxZHk5V1ctX3BUM0R4TGpLYlF5ZGItR0xPN2cifQ..Np4accZ6rX8N5MFXCYZEaVral45DhGwp2WEsMbsxrIacirruNml8auArmImYo8M57m3cyl8tf8d5wXCwx-1KwijT_uvkAl-v8CBcQU_2CmpJ-WrKvMlcHMm21-LAnxn2bqWnsgWDHX2W2buwDZTIZTfXrAQBl-5Ofa43GccU3TXin5i6feLXc8VVRC89D5kP45kjltSnXdS6cD3ZCjCDJLFLaWb-khaxENK_LrADRm2Zt3r7x-dXsKaKLxtyjYzNg005g5Ws528V6xWfZs5OKOys1VdYLH-1iVApCUGoC6ijlSN2F9CpNrStbGRxrqg-3gTy6zwxp9DOkSp8H7SUtQ"
},
"payload": {
"@context": {
"security": "https://w3id.org/security#"
},
"hello": "world"
},
"chain": [
{
"C": "CA",
"CN": "davidjanes.com",
"fingerprint": "78:EA:E2:A5:19:FD:A8:35:56:2D:59:B7:B7:20:32:6C:F6:EC:53:E0"
}
]
}
You can recreate this yourself:
cd information-passport/tools/bin
node verify.js --file signed.json --verifier ../data/public.cer.pem