DEV Community

Cover image for Mask On: A Code Journey into ID-Mask and Mina
DappaDan
DappaDan

Posted on

Mask On: A Code Journey into ID-Mask and Mina

Launching a mainnet is like that awkward moment when hosting a party.

You know the one.

At the start of the party when no one has come exactly on time you start to worry.

Are people fashionable late? Are they coming? Did I send the wrong date?

Of course, those worries go out the window once the first guest arrives.

In the case of the Mina Mainnet, ID-Mask is the first guest.

In this article, we will take a technical dive into ID-Mask and what it shows about the future of building ZKApps.

By the end of this article, you should feel inspired to start building your own ZKApps after realizing how accessible it is to develop on Mina.

So let's get this party started!

What is ID-Mask?

Proving your identity is something we do almost every day. Whether you're handing over a plastic ID card to get a nice beverage or a passport to enter a country. This requires us to carry these documents around and hand them over to people we may or may not trust.

Don't get me started on trying to port over my physical ids to the "digital world". The amount of times I have tried to take photos of my passport at the right angle for the OCR to work is countless.

ID-Mask aims to solve these problems. It's a service that allows users to generate Zero-Knowledge proofs to verify they are an adult, have no sanctions against them, and are a unique human. Users can now use the generated proof for identification purposes.

Goodbye plastic cards, hello ZK proofs!

How Does it Work?

Step 1: User Signature

Currently, the team has created an integration with a service called Smart-ID. This identification service lets users create digital, verifiable signatures through an application. The user's identification is stored on the Smart-ID platform, and any service integrating with it can create a signature request from the user.

These signatures can be used for a variety of different use cases. For example, when performing a large bank transaction, signing a contract, or approving new terms, integrating services can obtain data verification from the client side. This is because the user has approved the signature, confirming the data's validity.

ID-Mask uses this personal data as private inputs to respect the privacy of users:


methods: {
    proveUniqueHuman: {
      privateInputs: [
        PersonalData,
        Signature, // zkOracle data signature
        CircuitString, // unique secret value
        Signature, // signature of unique secret value
        Signature, // creator wallet signature
        PublicKey, // creator wallet public key
      ],
Enter fullscreen mode Exit fullscreen mode

Step 2: Consuming the Data and Creating Proofs

After receiving personal data from Smart-ID, a proof needs to be generated for that information.

To prevent data tampering during this process, ID Mask uses an oracle connected to the Smart-ID data:

     const validSignature = oracleSignature.verify(
          PublicKey.fromBase58(
          'B62qmXFNvz2sfYZDuHaY5htPGkx1u2E2Hn3rWuDWkE11mxRmpijYzWN'
          ),
          personalData.toFields()
        );
        validSignature.assertTrue();
Enter fullscreen mode Exit fullscreen mode

ID-Mask using the ZKProgram interface built into 'o1js' to create the proof. Here is an example for generating a proof of age:

export const proofOfAge = ZkProgram({
  name: 'ZkProofOfAge',
  publicInput: Field, // ageToProveInYears
  publicOutput: PublicOutput, // defined above
  methods: {
    proveAge: {
      privateInputs: [
        PersonalData,
        Signature, // zkOracle data signature
        Signature, // creator wallet signature
        PublicKey, // creator wallet public key
      ],
      async method(
        ageToProveInYears: Field,
        personalData: PersonalData,
        oracleSignature: Signature,
        creatorSignature: Signature,
        creatorPublicKey: PublicKey
      ): Promise<PublicOutput> {

Enter fullscreen mode Exit fullscreen mode

Step 3: Using the Proof

Now that you have created the proof, the question is what to do with it.

In the case of ID Mask, the proof is attached to a Mina address. This gives the ability for the user to also prove their identity by proving they are the owner of the address. Anyone can then send a confirmation message to that address, allowing the user to prove their ownership:

     const validSignature_ = creatorSignature.verify(
          creatorPublicKey,
          personalData.toFields()
        );
        validSignature_.assertTrue();
Enter fullscreen mode Exit fullscreen mode

Step 4: Verifying the Personal Data

To prove that the data meets a certain requirement, it needs to be processed. For example, to prove "Proof of Age," ID Mask extracts the date of birth from the personal identification number and compares it to the specified olderThanAgeToProve.

        const dateOfBirth = parseDateFromPNO(personalData.pno);       personalData.currentDate.greaterThan(dateOfBirth).assertTrue();
        // verify that (current date - age to prove) > date of birth
        const olderThanAgeToProve = personalData.currentDate
          .sub(ageToProveInYears.mul(Field(10000)))
          .greaterThan(dateOfBirth);
        olderThanAgeToProve.assertTrue();
Enter fullscreen mode Exit fullscreen mode

If the age is higher than the age to prove, a proof is created. If not, sorry kid...time to grow up.

Image description

Step 5: Emitting the Event

The final step is to create a smart contract that handles putting the proof on chain. This shows a major benefit of using a network like Mina: other applications can also use this proof.

export class ProofOfAge extends SmartContract {
  events = {
    'provided-valid-proof': PublicOutput,
  };
  init() {
    super.init();
    // https://docs.minaprotocol.com/zkapps/o1js/permissions#types-of-permissions
    this.account.permissions.set({
      ...Permissions.default(),
    });
  }
  @method async verifyProof(proof: ProofOfAgeProof) {
    // if the proof is invalid, this will fail
    // its impossible to run past this without a valid proof
    proof.verify();
    // the above is enough to be able to check if an address has a proof
    // but there needs to be a way to save the number of years that are proved
    // emit an event with number of years to be able to query it via archive nodes
    this.emitEvent('provided-valid-proof', proof.publicOutput);
  }
Enter fullscreen mode Exit fullscreen mode

The future of ID-Mask and ZKApps

The team at ID-Mask has some great ambitions to grow the use of this service. There is also a feature for storing these proofs in a mobile wallet like Apple or Google wallet. This brings this ability to more consumers who don't have a crypto wallet themselves.

Currently, Smart ID solution is limited to Baltic countries and Belgium. Other countries, such as Sweden and Switzerland, offer similar services, but they come with high costs. As the code is open source, more developers can start contributing to the expansion.

As consumer adoption grows for the use of ZK apps, so must the speed of proving. Especially if we are competing against systems that are more performant, even though they are less private. The team at Mina is aiming to make proving 8x faster soon.

If that is the case, I will leave you with one question, what are you going to build?

Top comments (0)