Integrar SSI en dApps: tutorial

Introducción a SSI y dApps

Self-Sovereign Identity (SSI) es un paradigma de identidad digital que permite al usuario controlar sus propios datos de identidad sin depender de un tercero centralizado. En el ecosistema cripto y blockchain, la integración de SSI en dApps (aplicaciones descentralizadas) aporta seguridad, privacidad y cumplimiento de regulaciones emergentes como GDPR.

Este tutorial detalla paso a paso cómo implementar SSI en una dApp basada en Ethereum. Cubriremos desde los conceptos teóricos hasta los fragmentos de código y configuración práctica.

¿Por qué SSI en dApps

  • Control del usuario: El titular de la identidad es el único que decide compartir sus atributos.
  • Menor superficie de ataque: No hay repositorios centralizados de datos personales.
  • Interoperabilidad: Basado en estándares W3C: DID Core y Verifiable Credentials.
  • Resiliencia: Puede operar offline y sincronizar transacciones luego.

Arquitectura de una dApp con SSI

De forma genérica, los componentes clave son:

  1. Wallet de SSI: Aplicación móvil o extensión que gestiona DIDs y credenciales verificables.
  2. Smart Contracts: Contratos en Ethereum que manejan registros públicos (p.ej. revocación de credenciales).
  3. Node de SSI: Servidor Aries o Hyperledger Indy para emisión y verificación de credenciales.
  4. dApp Front-end: Interfaz en React, Angular o Vue que orquesta Web3.js/Ethers.js y librerías SSI (p.ej. did-jwt-vc).

Diagrama de Flujo Simplificado

Paso Descripción
1 El usuario solicita la emisión de una credencial.
2 El issuer (emisor) crea un Verifiable Credential.
3 La credencial se almacena en el SSI Wallet del usuario.
4 El usuario presenta una prueba a la dApp para acceder a servicios.

Requisitos Previos

  • Node.js ≥ 14.x
  • Truffle o Hardhat
  • Ganache (o testnet de Ethereum: Ropsten/Rinkeby)
  • React ≥ 17.x (o framework de tu preferencia)
  • SSI Agent: Hyperledger Indy/Aries (Sovrin / Aries RFCs)
  • did-jwt-vc, @veramo/core u otra librería SSI

Paso 1: Configurar el SSI Agent

Instalación básica de un agente Aries Dockerizado:

docker run -d --name aries-agent 
  -p 8021:8021 
  -e ADMIN_API_KEY=adminpw 
  -e GENESIS_URL=https://sovrin-genesis.example.org/genesis 
  bcgovimages/aries-agent-java:latest

Verifica la API REST en http://localhost:8021/

Paso 2: Emisión de una Verifiable Credential

  • Define un schema y crea un credential definition en tu ledger.
  • Utiliza el endpoint /issue-credential del agente Aries:
POST http://localhost:8021/issue-credential/send
Content-Type: application/json
x-api-key: adminpw

{
  connection_id: abc123,
  credential_preview: {
    @type: issue-credential/2.0/credential-preview,
    attributes: [
      { name: nombre, value: María Pérez },
      { name: email, value: maria@example.com }
    ]
  },
  filter: { indy: { cred_def_id: Th7MpTaRZVRYnPiabds81Y:3:CL:20:default }}
}

Paso 3: Integrar en el Front-end de la dApp

Ejemplo usando React y ethers.js junto a did-jwt-vc:

import { createVerifiableCredentialJwt, verifyCredential } from did-jwt-vc
import { ethers } from ethers

// Inicializar provider y contrato
const provider = new ethers.providers.Web3Provider(window.ethereum)
const contractAddress = 0xYourContract
const abi = [ / ABI del smart contract / ]

// Función para solicitar presentación de credencial
async function requestPresentation() {
  const vcJwt = await wallet.getCredential(credDefId)
  const verified = await verifyCredential(vcJwt)
  if (verified.verifiableCredential) {
    // Llamar al smart contract con prueba
    const signer = provider.getSigner()
    const contract = new ethers.Contract(contractAddress, abi, signer)
    await contract.registerUser(verified.verifiableCredential.credentialSubject.did)
  }
}

Paso 4: Smart Contract para Registro de DID

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0

contract DIDRegistry {
  mapping(address => string) public dids
  event DIDRegistered(address indexed user, string did)

  function registerUser(string calldata did) external {
    require(bytes(dids[msg.sender]).length == 0, DID ya registrado)
    dids[msg.sender] = did
    emit DIDRegistered(msg.sender, did)
  }
}

Buenas Prácticas y Consideraciones

  • Revocación: gestiona listas de revocación en el ledger o utiliza status lists de W3C.
  • Privacidad: emplea Zero-Knowledge Proofs (ZKPs) si es necesario revelación mínima (iden3).
  • Usabilidad: la UX del wallet debe ser fluida y segura.
  • Seguridad: protege claves privadas en enclaves seguros o hardware wallets.

Recursos y Lecturas Adicionales

© 2024 Tutorial SSI en dApps. Todos los derechos reservados.


Comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *