Skip to content

Your First Credential

This tutorial walks through the complete credential lifecycle using BaseID. You will create an issuer, issue a credential, store it in a wallet, and verify it.

use baseid_core::types::KeyType;
use baseid_crypto::KeyPair;
use baseid_did::DidKeyResolver;
// Generate issuer identity
let issuer_kp = KeyPair::generate(KeyType::Ed25519)?;
let issuer_doc = DidKeyResolver::create(&issuer_kp.public)?;
let issuer_did = issuer_doc.id.clone();
let kid = issuer_doc.verification_method[0].id.clone();

The issuer needs a key pair and a DID. The kid (key ID) references the specific verification method used for signing.

use baseid_vc::{sign_credential_jwt, VerifiableCredential};
use baseid_vc::credential::Issuer;
let vc = VerifiableCredential {
context: vec!["https://www.w3.org/ns/credentials/v2".into()],
id: None,
r#type: vec!["VerifiableCredential".into(), "UniversityDegree".into()],
issuer: Issuer::Uri(issuer_did.clone()),
valid_from: Some("2024-01-01T00:00:00Z".into()),
valid_until: Some("2029-01-01T00:00:00Z".into()),
credential_subject: serde_json::json!({
"id": "did:key:z6MkHolder...",
"degree": {
"type": "BachelorDegree",
"name": "Computer Science"
}
}),
credential_status: None,
proof: None,
};
let jwt = sign_credential_jwt(&vc, &issuer_kp, &kid)?;
println!("Issued JWT: {jwt}");
use baseid_wallet_core::store::InMemoryStore;
use baseid_wallet_core::wallet::Wallet;
let store = InMemoryStore::new();
let wallet = Wallet::new(store, "did:key:z6MkHolder...".into());
// Receive and store the credential JWT

The wallet stores credentials and manages the holder’s key material. InMemoryStore is useful for testing; use a persistent store in production.

The wallet matches credentials against a presentation request and creates a Verifiable Presentation:

// The verifier sends a presentation request specifying which
// credential types and claims are needed.
// The wallet selects matching credentials and creates a VP.

In a real deployment, this exchange happens over OID4VP or DIDComm v2.

use baseid_vc::verify_credential_jwt;
let verified = verify_credential_jwt(&jwt, &issuer_kp.public)?;
println!("Issuer: {}", verified.issuer);
println!("Valid from: {:?}", verified.valid_from);
println!("Subject: {:?}", verified.credential_subject);

The verifier checks the cryptographic signature, ensures the credential has not expired, and extracts the claims.