Skip to main content

Working with Anonymous Credentials (AnonCreds)

danger

TODO: Not tested at all; everything could be wrong

Introduction

In this tutorial, we will explore how to use Veramo to issue and verify Anonymous Credentials (AnonCreds), which are often used in privacy-preserving identity systems. AnonCreds are typically associated with Hyperledger Indy, and they allow users to prove certain attributes about themselves without revealing their full identity.

This extends the previous "Formats" tutorial to show how Veramo extensions can be used to support other important standards.

Steps

Prerequisites

Before you begin, follow the prerequisites for installation and configuration instructions.

You will also need to have access to a Hyperledger Indy network, such as the Sovrin network, and the appropriate SDKs installed.

1. Initialize a DID for the Issuer

First, we will create a DID for a sample organization (issuer) using the did:indy method.

veramo did create

Select the following options:

? Select identifier provider did:indy
? Select key management system local
? Enter alias sample_issuer

Expected output:

┌──────────┬─────────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ provider │ alias │ did │
├──────────┼─────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ did:indy │ sample_issuer │ did:indy:sovrin:WRfXPg8dantKVubE3HX8pw │
└──────────┴─────────────────┴───────────────────────────────────────────────────────────────────────────────┘

2. Initialize a DID for the Holder

Next, we will create a DID for a sample individual (holder) using the did:indy method.

veramo did create

Select the following options:

? Select identifier provider did:indy
? Select key management system local
? Enter alias sample_holder

Expected output:

┌──────────┬─────────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ provider │ alias │ did │
├──────────┼─────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ did:indy │ sample_holder │ did:indy:sovrin:Fu4nD6uM2YnHHwPY7nB6eK │
└──────────┴─────────────────┴───────────────────────────────────────────────────────────────────────────────┘

3. Create an AnonCred Schema

AnonCreds require a schema that defines the attributes included in the credentials. Create a schema using the Hyperledger Indy SDK.

const indy = require("indy-sdk");

async function createSchema() {
const schemaName = "EmployeeCredential";
const schemaVersion = "1.0";
const schemaAttributes = [
"firstName",
"lastName",
"employeeId",
"department",
];

const [schemaId, schema] = await indy.issuerCreateSchema(
issuerDid,
schemaName,
schemaVersion,
schemaAttributes
);

return { schemaId, schema };
}

4. Create a Credential Definition

Create a credential definition for the schema using the Hyperledger Indy SDK.

async function createCredentialDefinition(schema) {
const tag = "employee_cred_def";
const [credDefId, credDef] = await indy.issuerCreateAndStoreCredentialDef(
issuerWallet,
issuerDid,
schema,
tag,
"CL",
{ support_revocation: false }
);

return { credDefId, credDef };
}

5. Issue an AnonCred

Issue an anonymous credential to the holder using the credential definition.

async function issueAnonCred() {
const credOffer = await indy.issuerCreateCredentialOffer(
issuerWallet,
credDefId
);

const masterSecretId = await indy.proverCreateMasterSecret(
holderWallet,
null
);

const [credRequest, credRequestMetadata] =
await indy.proverCreateCredentialReq(
holderWallet,
holderDid,
credOffer,
credDef,
masterSecretId
);

const credValues = {
firstName: {
raw: "John",
encoded: "1139481716457488690172217916278103335",
},
lastName: { raw: "Doe", encoded: "5321642780241790123587902456789123452" },
employeeId: { raw: "12345", encoded: "12345" },
department: { raw: "Engineering", encoded: "67890" },
};

const [credential] = await indy.issuerCreateCredential(
issuerWallet,
credOffer,
credRequest,
credValues,
null,
-1
);

await indy.proverStoreCredential(
holderWallet,
null,
credRequestMetadata,
credential,
credDef,
null
);
}

6. Verify an AnonCred

Verify the anonymous credential using the Veramo framework.

async function verifyAnonCred() {
const proofRequest = {
nonce: "123432421212",
name: "Proof of Employment",
version: "1.0",
requested_attributes: {
attr1_referent: {
name: "firstName",
restrictions: [{ cred_def_id: credDefId }],
},
attr2_referent: {
name: "lastName",
restrictions: [{ cred_def_id: credDefId }],
},
attr3_referent: {
name: "employeeId",
restrictions: [{ cred_def_id: credDefId }],
},
attr4_referent: {
name: "department",
restrictions: [{ cred_def_id: credDefId }],
},
},
requested_predicates: {},
};

const credsForProof = await indy.proverGetCredentialsForProofReq(
holderWallet,
proofRequest
);

const requestedCredentials = {
self_attested_attributes: {},
requested_attributes: {
attr1_referent: {
cred_id:
credsForProof["attrs"]["attr1_referent"][0]["cred_info"]["referent"],
revealed: true,
},
attr2_referent: {
cred_id:
credsForProof["attrs"]["attr2_referent"][0]["cred_info"]["referent"],
revealed: true,
},
attr3_referent: {
cred_id:
credsForProof["attrs"]["attr3_referent"][0]["cred_info"]["referent"],
revealed: true,
},
attr4_referent: {
cred_id:
credsForProof["attrs"]["attr4_referent"][0]["cred_info"]["referent"],
revealed: true,
},
},
requested_predicates: {},
};

const proof = await indy.proverCreateProof(
holderWallet,
proofRequest,
requestedCredentials,
masterSecretId,
schemas,
credDefs,
revStates
);

const verified = await indy.verifierVerifyProof(
proofRequest,
proof,
schemas,
credDefs,
revRegDefs,
revRegs
);

return verified;
}

Conclusion

In this tutorial, we demonstrated how to use Veramo to issue and verify Anonymous Credentials (AnonCreds) using the Hyperledger Indy network. AnonCreds provide a powerful way to ensure privacy-preserving identity solutions, allowing users to prove specific attributes about themselves without revealing their full identity. Veramo's flexibility and support for various DID methods and proof formats make it an excellent choice for implementing decentralized identity solutions.