caelum-vcdm 0.1.2

This crates implements w3's Verifiable Credential Data Model
Documentation
caelum-vcdm-0.1.2 is not a library.

Verifiable Credential Data Model [WIP]

This crates implements w3's Verifiable Credential Data Model specifications. This means it will create, read, update and delete (a.k.a. CRUD) all properties of a Verifiable Credentialand a Verifiable Presentation. As well as interacting with other Verifiable Credential and Verifiable Presentation.

A Verifiable Credential or a Verifiable Presentation can represent all of the same information that a physical credential represents. The addition of technologies, such as digital signatures, makes verifiable credentials more tamper-evident and more trustworthy than their physical counterparts. In the physical world, a credential might consist of:

  • Information related to identifying the subject of the credential (for example, a photo, name, or identification number)
  • Information related to the issuing authority (for example, a city government, national agency, or certification body)
  • Information related to the type of credential this is (for example, a Dutch passport, an American driving license, or a health insurance card)
  • Information related to specific attributes or properties being asserted by the issuing authority about the subject (for example, nationality, the classes of vehicle entitled to drive, or date of birth)
  • Evidence related to how the credential was derived
  • Information related to constraints on the credential (for example, expiration date, or terms of use).

We want to help developers create these scenarios and making it easy to interact with other following the same specifications.

Prerequisites

  • Clang >= 8.0 clear_on_drop library needs Clang >= 8.0, otherwise clang won't recognize the wasm32-unknown-unknown triple defined by this architecture.

    • Install clang 8.0 in Ubuntu/Debian:
    sudo apt-install clang-8
    

    Configure update-alternatives to work aside with multiple clang versions (Sets Clang 8 as default version):

    sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-8 100
    sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-8 100
    

Installation

Rust

Add gitlab repository to Cargo.toml:

[dependencies]
caelum-vcdm = "*"
...

Javascript

yarn add @caelum-tech/caelum-vcdm

Now the library is installed for javascript. In order to be able to use a wasm library in javascript follow the following steps:

  1. Create in root a file called config-overrides.js with the following code in it:
const path = require('path');

module.exports = function override(config, env) {
    const wasmExtensionRegExp = /\.wasm$/;

    config.resolve.extensions.push('.wasm');

    config.module.rules.forEach(rule => {
        (rule.oneOf || []).forEach(oneOf => {
            if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) {
                // make file-loader ignore WASM files
                oneOf.exclude.push(wasmExtensionRegExp);
            }
        });
    });

    // add a dedicated loader for WASM
    config.module.rules.push({
        test: wasmExtensionRegExp,
        include: path.resolve(__dirname, 'src'),
        use: [{ loader: require.resolve('wasm-loader'), options: {} }]
    });

    return config;
};
  1. Install wasm-loader

yarn add wasm-loader

  1. Load wasm library in component. Add this code:
let vcdm ;
try {
    vcdm = await import('caelum-vcdm');
} catch(err) {
    console.error(`Unexpected error in loadWasm. [Message: ${err.message}]`);
    return undefined
}
let claim = new vcdm.VClaim("my_id".toString());
console.log("Claim created: ", claim);

Getting started with JavaScript

// Constructing a Claim
let claim = new vcdm.VClaim()
    .setCredentialStatus({id: "my_id", type: "EmailCredential"})
    .setCredentialType(["EmailCredential", "VerifiableCredential"])
    .setCredentialSubject({email: "foo@bar.com"})
    .setId("my_id")
    .setIssuanceDate("2018-06-17T10:03:48Z")
    .setIssuer("did:example:issuer");

console.log(claim.toJSON());

// Contructing a Verifiable Credential
let vc = new vcdm.VCredential("my_id")
    // Setters overwrite values of property
    .setIssuer("Issuer")
    .setClaim(claim.toJSON())
    // Setting another credential totally different and defined by user
    .setProof({
        "type": "RsaSignature2018",
        "created": "2018-06-17T10:03:48Z",
        "verificationMethod": "did:example:ebfeb1276e12ec21f712ebc6f1c#k1",
        "signatureValue": "pY9...Cky6Ed = "
    })
    // Adders push values to the vector properties
    .addContext("added context")
    .addType("added type");

console.log(vc.toJSON());

// Contructing a Verifiable Presentation
let vp = new vcdm.VPresentation("my_id")
    .addContext("added Context")
    .addType("added type")
    // Add the created Verifiable Credential
    .addVerifiableCredential(vc.toJSON())
    .setProof({
        "type": "RsaSignature2018",
        "created": "2018-06-17T10:03:48Z",
        "verificationMethod": "did:example:ebfeb1276e12ec21f712ebc6f1c#k1",
        "signatureValue": "pY9...Cky6Ed = "
    });

console.log(vp.toJSON());

or equivalently...

let vp_json = {
    "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1",
        "added Context"
    ],
    "id": "did:example:ebfeb1276e12ec21f712ebc6f1c",
    "type": [
        "VerifiableCredential",
        "PersonalInformation",
        "added type"
    ],
    "verifiableCredential": [
        {
             "@context": [
                 "https://www.w3.org/2018/credentials/v1",
                 "https://www.w3.org/2018/credentials/examples/v1"
             ],
             "type": ["VerifiableCredential"],
             "id": "my_id",
             "issuer": "Issuer",
             "claims": [{
                "id": "my_id",
                "credentialStatus": {
                    "id": "my_id",
                    "type": "EmailCredential"
                },
                "credentialSubject": [
                    {"email": "foo@bar.com"}
                ],
                "issuer": "did:example:issuer",
                "issuanceDate": "2018-06-17T10:03:48Z",
                "type": ["EmailCredential", "VerifiableCredential"]
             }],
             "proof": [{
                "type": "RsaSignature2018",
                "created": "2018-06-17T10:03:48Z",
                "verificationMethod": "did:example:ebfeb1276e12ec21f712ebc6f1c#k1",
                "signatureValue": "pY9...Cky6Ed = "
             }],
             "nonRevocationProof": [{
                 "type": "",
                 "created": "",
                 "verificationMethod": "",
                 "signatureValue": ""
             }]
         }
    ],
    "proof": {
        "type": "RsaSignature2018",
        "created": "2018-06-17T10:03:48Z",
        "verificationMethod": "did:example:ebfeb1276e12ec21f712ebc6f1c#k1",
        "signatureValue": "pY9...Cky6Ed = "
    }
};

let vp = vcdm.VPresentation.fromJSON(vp_json);

console.log(vp.toJSON());

Signing (Javascript)

Linked Data (Javascript)

// Signature from claim
let claim = new vcdm.VClaim()
    .setCredentialStatus({id: "my_id", type: "EmailCredential"})
    .setCredentialType(["EmailCredential", "VerifiableCredential"])
    .setCredentialSubject({email: "foo@bar.com"})
    .setId("my_id")
    .setIssuanceDate("2018-06-17T10:03:48Z")
    .setIssuer("did:example:issuer");
const keys = new Uint8Array(64);
const signature = claim.sign(keys)
console.log(signature)

// Proof from claim (signature is created automatically)
const proof = vcdm.VProof.fromClaimAndKeys(claim.toJSON(), keys)

// Verify signature from proof & claim
console.log(
    vcdm.verifyClaim(claim.toJSON(), proof.toJSON())
)

// Verify signature from claim
console.log(
    claim.verify(proof.toJSON())
)

Zenroom (Javascript)

Not implemented

Getting started with Rust

let vc_json_str = r#"{
    "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1"
    ],
    "type": ["VerifiableCredential"],
    "id": "",
    "issuer": "",
    "claims": [{
        "id": "",
        "credentialStatus": {
            "id": "",
            "type": ""
        },
        "credentialSubject": [],
        "issuer": "",
        "issuanceDate": "",
        "type": ["VerifiableCredential"]
    }],
    "proof": [{
        "type": "",
        "created": "",
        "verificationMethod": "",
        "signatureValue": ""
    }],
    "nonRevocationProof": [{
        "type": "",
        "created": "",
        "verificationMethod": "",
        "signatureValue": ""
    }]
}"#;

let _ver_cred_from_json: VerifiableCredential = serde_json::from_str(vc_json_str).unwrap();

Equivalent to:

let mut ver_cred_vcdm =
            VerifiableCredential::new("http://example.com/credentials/4643".to_string());
ver_cred_vcdm.set_proof(
    serde_json::from_str(r#"{
        "type": "RsaSignature2018",
        "created": "2018-06-17T10:03:48Z",
        "verificationMethod": "did:example:ebfeb1276e12ec21f712ebc6f1c#k1",
        "signatureValue": "pY9...Cky6Ed = "
    }"#).unwrap()
);
ver_cred_vcdm.set_credential_subject(
    serde_json::from_str(r#"{
        "type": "did:example:abfab3f512ebc6c1c22de17ec77",
        "name": "Mr John Doe",
        "mnumber": "77373737373A",
        "address": "10 Some Street, Anytown, ThisLocal, Country X",
        "birthDate": "1982-02-02-00T00:00Z"
    }"#).unwrap()
);
ver_cred_vcdm.set_issuance_date("2010-01-01T19:73:24Z".to_string());
ver_cred_vcdm.set_issuer("did:example:ebfeb1276e12ec21f712ebc6f1c".to_string());
ver_cred_vcdm.set_credential_status(
    serde_json::from_str(r#"{
        "id": "cred_stat_id",
        "type": "cred_stat_credential_subject_type"
    }"#).unwrap(),
);

Signing (Rust)

There are two types of signing claims, with Linked Data or using Zenroom.

Linked Data (Rust)

// Signature from claim
ley keys = vec![
        212, 109, 1, 120, 214, 102, 78, 169, 141, 239, 187, 76, 224, 61, 74, 250, 20, 4,
        89, 89, 159, 113, 116, 168, 87, 79, 196, 25, 155, 87, 180, 134, 65, 189, 48, 58, 3,
        235, 0, 194, 39, 238, 5, 140, 57, 222, 169, 56, 62, 89, 169, 66, 225, 253, 97, 6,
        241, 72, 72, 72, 195, 209, 12, 81,
    ];
// Creating Claim
let c: Claim = serde_json::from_str(r#"{"credentialStatus":{"id":"Hash: 0x8633385811f06e22d5f62eb958c8b1a72a6fbcf59c6f464f9d3b7d086355ab3d","type":"pending"},"type":["VerifiableCredential","CaelumEmailCredential"],"credentialSubject":[{"email":"asd","last":"","type":"CaelumEmailCredential","first":""}],"id":"Hash: 0xa76745d559991b293036244416c6818b15d8debf6960151d4c6abf5b284fbb1b","issuanceDate":"2019-10-16T14:07:41.657Z","issuer":"did:lrn:caelum-email-verifier:ebfeb1276e12ec21f712ebc6f1c#k2"}"#).unwrap();

// Proof from claim (signature is created automatically)
let p: Proof = Proof::from_claim_and_keys(
    &c,
    &keys,
);

// Verify signature from proof & claim
assert_eq!(verify_claim(&c, &p), Ok(()));

// Verify signature from claim
println!("{:#?}",
    c.verify(&p)
)

Zenroom (Rust)

Not implemented

Roadmap

  • [ X ] Basic CRUD implementation on properties.
  • [ X ] Basic CRUD implementation on Optional properties.
  • [ X ] Verifying basic cryptographic proofs.
  • Implementation of Zero-Knowledge proof using Zenroom.
  • Connecting to Verifiable Data Registry.
  • Validation for necessary properties.
  • Implementation of Roles (Issuer, Holder, Verifier).

Contributing

Please, contribute to vcdm! The more the better! Feel free to to open an issue and/or contacting directly with the owner for any request or suggestion.

Acknowledgment

This library is created to satisfy w3's specifications.

Code of conduct

This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at http://contributor-covenant.org/version/1/4

License

This project is distributed under the terms of both the Apache License (Version 2.0) and the MIT license, specified in LICENSE-APACHE and LICENSE-MIT respectively.