zkPass
zkPass Developer's Guide
zkPass Developer's Guide
  • â›Šī¸Introduction
  • ZKPASS OVERVIEW
    • đŸ›ī¸Architecture
    • 🧱zkPass Components
    • 🤝Trust Models
    • 🚚Deployment
      • Public-Cloud Hosting
      • Private-Cloud Hosting
      • On-Premise Hosting
    • đŸŽ¯SDK Objectives
    • 🔑API Key
  • zkPass Modules
    • â˜ī¸DVR
      • đŸ—ģHigh Level View
      • đŸ—ī¸Key Concepts
        • User Data
        • DVR Info
        • zkPass Proof
      • đŸ‘ĨDVR Client Roles
        • Data Issuer
          • Providing User Data Retrieval API
        • Data Holder
          • 1. Retrieving the DVR
          • 2. Retrieving the User Data
          • 3. Generating the Proof
          • 4. Verifying the Proof
        • Proof Verifier
          • 1. Providing DVR Retrieval API
          • 2. Providing Proof Verification API
      • 🔎DVR Query
        • Building Query Engine
        • Processing Query
        • Query Grammar
      • đŸ—ī¸Integration Guidelines
      • 🌊DVR Workflows
  • SDK Tutorial
    • Typescript
      • Running Code
      • Code Snippet
      • Directory Structure
    • Rust
      • Running Code
      • Code Snippet
      • Directory Structure
  • API Reference
    • Typescript
      • Classes
        • Class: DvrModuleClient
      • Functions
        • Functions: ffiHelper
        • Functions: jwtHelper
        • Functions: publicKeyOptionUtils
      • Type Aliases
        • Types
        • Types: ffiType
      • Interfaces
        • Interfaces
      • Constants
        • Constants
        • Enums
      • Errors
    • Rust
      • Building Rust doc
    • RESTful API
      • Overview
      • Endpoints
        • Generate Proof
      • Utilities
        • Generate Key Pair
        • Sign User Data and DVR
        • Encrypt User Data and DVR
      • Errors
  • Glossary
    • DVR
    • User Data
    • ZKP
Powered by GitBook
On this page
Export as PDF
  1. zkPass Modules
  2. DVR
  3. DVR Client Roles

Data Issuer

PreviousDVR Client RolesNextProviding User Data Retrieval API

Last updated 6 months ago

The Data Issuer only needs to follow this step for integration with the zkPass Service:

Sample Implementation

Sample codes for the Data Issuer implementation follow. Each step is explained in detail in the subsections. The code is also available on the zkpass-sdk repo, as shown here:

â˜ī¸
đŸ‘Ĩ
Providing REST API for user data retrieval
https://github.com/gl-zkPass/zkpass-sdk/blob/main/rust/zkpass-demo/src/data_issuer.rs
/*
 * data_issuer.rs
 * Simulating the Data Issuer process for the zkPass Demo
 *
 * ---
 * References:
 *   https://docs.ssi.id/zkpass/zkpass-developers-guide/privacy-apps/dvr/dvr-client-roles/data-issuer
 * ---
 * Copyright (c) 2024 PT Darta Media Indonesia. All rights reserved.
 */
use crate::{ sample_keys::ISSUER_PRIVKEY, lib_loader::generate_user_data_token };
use dvr_types::PublicKeyOptionFfi;
use serde_json::Value;
use std::{ collections::HashMap, io::prelude::*, ffi::CString };
use tracing::info;

// This struct ensures that the data reference is valid
#[allow(dead_code)]
pub struct IssuerPublicKeyOptionHolder {
    jku: CString,
    kid: CString,
    empty_str: CString,
    pub public_key_option: PublicKeyOptionFfi,
}

//
//  Simulating the REST call to the Data Issuer
//
pub struct DataIssuer;

//
//  Simulating the Data Issuer
//
impl DataIssuer {
    //
    // This function simulates the Data Issuer's get_user_data_token REST API
    //
    pub fn get_user_data_tokens(
        &self,
        data_files: HashMap<String, String>
    ) -> HashMap<String, String> {
        //
        // Call the dvr_client.dvr_generate_user_data_token.
        // This is to digitally-sign the user data.
        //
        data_files
            .iter()
            .map(|(data_tag, data_file)| {
                let data = self.read_user_data_token(data_file);
                let data_token = self.sign_user_data_token(data);
                (data_tag.clone(), data_token)
            })
            .collect()
    }

    ///
    /// Signs the user data token.
    ///
    fn sign_user_data_token(&self, data: Value) -> String {
        let user_data_token = unsafe {
            generate_user_data_token(ISSUER_PRIVKEY, &data.to_string())
        };

        user_data_token
    }

    ///
    /// Reads the user data token from the given file path.
    ///
    fn read_user_data_token(&self, data_file: &String) -> Value {
        let mut data_content = std::fs::File
            ::open(data_file)
            .expect("Cannot find the user data file");
        let mut data = String::new();
        data_content.read_to_string(&mut data).expect("Should not have I/O errors");
        info!("data={}", data);

        let data: Value = serde_json::from_str(&data).unwrap();
        data
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn add_dummy_file() {
        let data = r#"{"name": "Alice", "age": 25}"#;
        std::fs::write("./user_data_1.json", data).expect("Unable to write file");
        std::fs::write("./user_data_2.json", data).expect("Unable to write file");
    }

    fn remove_dummy_file() {
        std::fs::remove_file("./user_data_1.json").expect("Unable to remove file");
        std::fs::remove_file("./user_data_2.json").expect("Unable to remove file");
    }

    // on cargo llvm-cov nextest, this test is failing because of SIGSEGV (due to unsafe behavior), but not on cargo test
    #[ignore]
    #[test]
    fn test_get_user_data_tokens() {
        add_dummy_file();
        std::env::set_var(
            "DVR_MODULE_PATH",
            "/home/builder/zkPass/target/release/libdvr_client.so"
        );

        let data_issuer = DataIssuer;
        let data_files = vec![
            ("tag1".to_string(), "./user_data_1.json".to_string()),
            ("tag2".to_string(), "./user_data_2.json".to_string())
        ]
            .into_iter()
            .collect();

        let user_data_tokens = data_issuer.get_user_data_tokens(data_files);
        assert_eq!(user_data_tokens.len(), 2);
        remove_dummy_file();
    }

    #[test]
    #[should_panic]
    fn test_read_user_data_token_error() {
        let data_issuer = DataIssuer;
        let data_file = "./user_data_3.json".to_string();

        let _ = data_issuer.read_user_data_token(&data_file);
    }
}