InicioDocumentación

Documentación de Sparker Verify

Aprenda a integrar la verificación de medios respaldada por hardware en su aplicación. Desde el inicio rápido hasta la captura en navegador y la verificación pública.

Referencia de API

Visión General

Sparker Verify evita que medios generados por IA, editados o re-subidos sean presentados como capturas auténticas. Vincula cada archivo de imagen, video o audio a una clave privada respaldada por hardware en el dispositivo físico del usuario en el momento de la captura, y luego envuelve la prueba criptográfica en un manifiesto C2PA que cualquier tercero puede verificar de forma independiente.

Firma respaldada por hardware

Claves ECDSA P-256 generadas dentro del hardware seguro. Actualmente el SDK soporta WebAuthn en el navegador; el soporte nativo para iOS y Android está planificado.

Protocolo de desafío Nonce

Cada verificación utiliza un Nonce generado por el servidor con 5 minutos de tiempo de vida (TTL) para evitar ataques de repetición.

Verificación pública

Cualquiera puede verificar la autenticidad de los medios usando la API pública o el SDK. Los archivos nunca salen del cliente.

Entidades

EntidadRol
Provedor (Dispositivo Cliente)Posee la clave privada respaldada por hardware, firma el hash de archivo + nonce
Verificador (Servidor Sparker)Orquesta desafíos, valida firmas, genera manifiestos C2PA
Tercero interesado (Negocio)Consume medios verificados y comprueba su autenticidad mediante la API pública

Autenticación

Sparker utiliza Google OAuth para el acceso al panel y claves de API gestionadas desde el panel para el tráfico del SDK. Inicialice el SDK una vez con una clave de API y este asociará las solicitudes de verificación a esa cuenta. Los endpoints de verificación pública siguen funcionando sin autenticación, pero tienen límites de velocidad mucho más estrictos.

Para la captura delegada a terceros, los tokens de enlace de verificación 3P le permiten compartir la capacidad de verificación con personas que no tienen cuentas de Sparker. Consulte la para más detalles.

Inicio Rápido

El SDK ahora cuenta con dos rutas rápidas: una capa de superposición de verificación para medios publicados y un componente de captura para envíos en vivo desde el navegador.

1. Instalar el SDK

bash
npm install @sparker-io/verify-sdk

2. Envolver una imagen publicada

typescript
import { SparkerVerify } from '@sparker-io/verify-sdk'
import { SparkerVerifiedImage } from '@sparker-io/verify-sdk/react'

const client = new SparkerVerify({
  apiUrl: 'https://verify.sparker.io',
  appUrl: 'https://verify.sparker.io',
  apiKey: 'spk_live_...',
})

export function StoryImage() {
  return (
    <SparkerVerifiedImage client={client}>
      <img
        src="/story/harbor-wall.jpg"
        alt="Equipos de concreto reforzando el muro del puerto"
      />
    </SparkerVerifiedImage>
  )
}

3. Integrar el panel de captura

El componente de captura de React maneja el registro del navegador en la primera ejecución, la creación de nonces, la generación de firmas y la subida de archivos.

typescript
import { SparkerCapture } from '@sparker-io/verify-sdk/react'

export function CaptureDesk() {
  return (
    <SparkerCapture
      apiKey="spk_live_..."
      apiUrl="https://verify.sparker.io"
      appUrl="https://verify.sparker.io"
      onVerified={(result) => {
        console.log(result.id)
        console.log(result.signature_hash)
        console.log(result.verificationUrl)
      }}
    />
  )
}

4. Utilizar el cliente de bajo nivel cuando sea necesario

typescript
const sdk = new SparkerVerify({
  apiUrl: 'https://verify.sparker.io',
  appUrl: 'https://verify.sparker.io',
  apiKey: 'spk_live_...',
})

await sdk.registerBrowserDevice('Navegador de Reportero de Campo')

const verification = await sdk.submitCapturedFile(file, {
  metadata: {
    gps: {
      latitude: 40.7128,
      longitude: -74.006,
      accuracy: 8,
    },
  },
})

console.log(verification.signature_hash)
console.log(
  sdk.buildVerificationUrl(
    verification.signature_hash,
    undefined,
    verification.id,
  ),
)
Siguientes pasos
  • Lea el concepto del para entender cómo funciona bajo el capó.
  • Explore la Referencia de la API para conocer todos los endpoints disponibles.
  • Revise la demostración de Next.js en sdk/examples/nextjs-demo/ para ver un ejemplo de integración al estilo de una sala de redacción.

Conceptos

Entender estos conceptos clave le ayudará a integrar Sparker Verify de manera efectiva y a tomar decisiones arquitectónicas fundamentadas.

Estándar C2PA

La Coalición para la Procedencia y Autenticidad del Contenido (C2PA) es un estándar técnico abierto que proporciona una forma de rastrear el origen y la historia del contenido digital. Sparker Verify utiliza manifiestos C2PA para incrustar datos de procedencia criptográfica directamente en los archivos de medios.

Un manifiesto C2PA contiene reclamaciones (claims) e afirmaciones (assertions). Sparker crea una afirmación personalizada llamada Hardware Verified Capture que registra:

  • La prueba de atestación de hardware (plataforma del dispositivo, formato de atestación)
  • El nonce utilizado durante la captura (un solo uso, TTL de 5 minutos)
  • El estado de verificación de la firma del dispositivo (verificada contra la clave pública almacenada)
  • Coordenadas GPS al momento de la captura (si se proporcionan)
  • Información del dispositivo (nombre, modelo, plataforma)

El manifiesto se firma con la cadena de certificados X.509 de la plataforma, lo que lo hace verificable de forma independiente por cualquier herramienta compatible con C2PA.

Compatibilidad C2PA
Los manifiestos de Sparker son compatibles con C2PA v1.3+. Cualquier herramienta que lea metadatos C2PA (Adobe Content Credentials, Truepic, etc.) puede verificar los medios firmados por Sparker.

Atestación de hardware

La atestación de hardware demuestra que una clave criptográfica fue generada y está almacenada dentro de un Entorno de Ejecución Seguro (TEE). Esto ofrece una garantía sólida de que la clave de firma no puede ser extraída, copiada ni utilizada únicamente mediante software.

PlataformaEstadoFormato de atestaciónNotas
WebSoportado hoywebauthnCaptura desde navegador y registro de dispositivos a través de WebAuthn
iOSPlanificadoNo soportado aúnEl SDK nativo para iOS y el flujo Secure Enclave no están disponibles todavía
AndroidPlanificadoNo soportado aúnEl SDK nativo para Android y el flujo StrongBox / TEE no están disponibles todavía

Los registros de dispositivos compatibles actualmente utilizan el flujo WebAuthn del navegador y envían claves públicas en un formato unificado: {algorithm: "ES256", x: "<base64>", y: "<base64>"}. Los formatos nativos de iOS y Android seguirán el mismo modelo del lado del servidor una vez que se lancen esos SDKs.

Seguridad de las claves
Las claves respaldadas por hardware no se pueden exportar del dispositivo. Si un dispositivo se pierde o se restablece de fábrica, el par de claves se destruye permanentemente. Se recomienda registrar múltiples dispositivos como respaldo.

Flujo de verificación

El ciclo de vida de la verificación consta de tres fases: registro de dispositivo, captura de medios con firma, y verificación pública.

Fase 1: Registro del dispositivo (una sola vez)

Cliente                                 Servidor
  |                                       |
  |--- POST /devices/challenge ---------->|
  |<-- { challenge } ---------------------|
  |                                       |
  |  [generar par de claves en TEE]       |
  |  [firmar desafío con clave privada]   |
  |  [recopilar prueba de atestación]     |
  |                                       |
  |--- POST /devices/register ----------->|
  |    { platform, device_id,             |
  |      public_key, attestation }        |
  |                                       |
  |    [verificar challenge_response]     |
  |    [verificar cadena de atestación]   |
  |    [guardar public_key + device_id]   |
  |                                       |
  |<-- { id, device_id, platform } -------|

Fase 2: Capturar y firmar

Cliente                                 Servidor
  |                                       |
  |--- POST /verifications -------------->|
  |<-- { id, nonce, expires_at } ---------|
  |                                       |
  |  [capturar medio en vivo]             |
  |  [calcular SHA-256(archivo + nonce)]  |
  |  [firmar hash con clave de hardware]  |
  |                                       |
  |--- POST /verifications/verify ------->|
  |    { id, file, device_id,             |
  |      signature, metadata }            |
  |                                       |
  |    [verificar nonce válido e inédito] |
  |    [buscar dispositivo por device_id] |
  |    [verificar firma con clave pública]|
  |    [crear manifiesto C2PA]            |
  |    [guardar archivo + registrar hash] |
  |                                       |
  |<-- { authentic,                       |
  |      signature_hash } ---------------|

Fase 3: Verificación pública

Los terceros interesados verifican la autenticidad de los medios sin necesidad de subir los archivos. El hash de la firma (cadena hexadecimal de 64 caracteres extraída del manifiesto C2PA) se contrasta con el registro de Sparker.

typescript
// Verificación del lado del cliente (sin subir el archivo)
const result = await sdk.verifySignature('abc123def456...')
if (result.authentic) {
  console.log('Verificado el:', result.verified_at)
}

Guías

Integración web

Integre Sparker Verify en su aplicación web utilizando el SDK de JavaScript. Esta guía cubre el flujo completo desde la configuración inicial hasta la verificación.

Prerrequisitos

  • Una cuenta en Sparker con acceso a la API
  • Un navegador moderno con soporte para WebAuthn (Chrome 67+, Firefox 60+, Safari 14+)
  • HTTPS habilitado en su dominio (requerido para WebAuthn)

Configuración de autenticación

Genere una clave de API en el panel de control e inicialice el SDK con ella. El inicio de sesión por OAuth se encarga de las sesiones del panel, pero el SDK debe utilizar la clave de API.

typescript
const sdk = new SparkerVerify({
  apiUrl: 'https://verify.sparker.io',
  appUrl: 'https://verify.sparker.io',
  apiKey: 'spk_live_...',
})

Comprobar soporte de WebAuthn

typescript
import { isWebAuthnAvailable } from '@sparker-io/verify-sdk'

if (!isWebAuthnAvailable()) {
  // Mostrar alternativa: WebAuthn no soportado
  showError('Su navegador no soporta la firma respaldada por hardware.')
}

Gestión de errores

El SDK arroja errores tipados que puede capturar y gestionar adecuadamente.

typescript
import { SparkerError } from '@sparker-io/verify-sdk'

try {
  const result = await sdk.submitCapturedFile(file)
} catch (error) {
  if (error instanceof SparkerError && error.status === 429) {
    // Límite de velocidad excedido - reintentar tras una pausa
    showRateLimitWarning(60)
  } else if (error instanceof SparkerError && error.status === 400) {
    // Solicitud incorrecta - verifique los parámetros de entrada
    showError(error.message)
  } else {
    showError('La verificación falló. Por favor, inténtelo de nuevo.')
  }
}

Uso del SDK

El SDK está diseñado pensando en primer lugar en los componentes. Utilice la capa de React para una adopción rápida, o recurra al cliente de bajo nivel para interfaces personalizadas o flujos fuera de React.

Soporte de plataforma actual
El SDK en producción solo soporta la captura desde el navegador y el registro del dispositivo. Los SDK nativos para iOS y Android no están soportados todavía.

Capa de superposición de verificación

Envuelva una imagen existente, deje que el SDK obtenga sus bytes, resuelva el hash de búsqueda y muestre el distintivo verde compacto en la esquina. Cuando el servidor devuelve un ID de verificación coincidente, el distintivo enlaza directamente a la página de verificación correspondiente.

typescript
import { SparkerVerify } from '@sparker-io/verify-sdk'
import { SparkerVerifiedImage } from '@sparker-io/verify-sdk/react'

const client = new SparkerVerify({
  apiUrl: 'https://verify.sparker.io',
  appUrl: 'https://verify.sparker.io',
  apiKey: 'spk_live_...',
})

<SparkerVerifiedImage client={client}>
  <img src={imageUrl} alt="Fotografía de campo" />
</SparkerVerifiedImage>

Flujo de captura

SparkerCapture se encarga del registro, la solicitud de nonce, el paso de la firma en el navegador y la subida a Sparker.

typescript
import { SparkerCapture } from '@sparker-io/verify-sdk/react'

<SparkerCapture
  apiKey="spk_live_..."
  apiUrl="https://verify.sparker.io"
  appUrl="https://verify.sparker.io"
/>

Verificación de bajo nivel

typescript
const sdk = new SparkerVerify({
  apiUrl: 'https://verify.sparker.io',
  appUrl: 'https://verify.sparker.io',
  apiKey: 'spk_live_...',
})

// Opción 1: Verificar mediante hash de búsqueda
const lookupHash = 'abc123...'
const result = await sdk.verifySignature(lookupHash)

// Opción 2: Verificar un archivo local
const local = await sdk.verifyFile(file)

// Opción 3: Verificar una URL de imagen publicada
const remote = await sdk.verifySource(imageUrl)

// Construir la URL pública de verificación
const url = sdk.buildVerificationUrl(
  lookupHash,
  imageUrl,
  result.verification_id,
)
Privacidad por diseño
Las búsquedas de verificación son muy ligeras. El SDK prioriza el hash de firma incrustado en el manifiesto C2PA cuando puede leerlo, y recurre al hash del archivo final en caso de ser la ruta de búsqueda activa.
Modelo de autenticación actual
Los flujos del SDK deben utilizar claves de API generadas desde el panel de control. Para capturas delegadas, proporcione un token de enlace de verificación 3P en su lugar.

Enlaces de verificación 3P

Los enlaces de verificación 3P permiten a los usuarios autenticados delegar la captura a terceros que no poseen cuentas en Sparker. Los casos de uso habituales incluyen reclamaciones de seguros, flujos de trabajo periodísticos y documentación sobre el terreno.

Crear un enlace de verificación 3P

typescript
// Crear un token con 10 usos que expira en 7 días
const token = await sdk.createToken({
  max_uses: 10,
  expires_at: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
})

// Compartir el enlace
console.log(token.url)
// https://verify.sparker.io/capture?token=...

Cómo funcionan los enlaces 3P

  1. El usuario abre el enlace de verificación 3P. No requiere registro ni inicio de sesión.
  2. El token se valida contra el servidor. Los tokens expirados o no válidos muestran un error.
  3. El usuario realiza la captura directamente a través de la cámara del navegador.
  4. La verificación queda asociada a la cuenta y cuota del creador del token.
  5. El contador de usos del token se incrementa. Al alcanzar los usos máximos, el token expira.

Gestionar tokens

typescript
// Listar todos sus tokens
const { tokens } = await sdk.listTokens()

// Revocar un token
await sdk.revokeToken(tokenId)

// Comprobar validez de un token (público, sin autenticación)
const status = await sdk.validateToken('token-string')
console.log(status.valid, status.remaining_uses)
Uso de cuota
Las verificaciones creadas mediante enlaces 3P se descuentan de la cuota del creador del token, no de la del participante. Revise su cuota en el panel para evitar exceder los límites.

Referencia del SDK

Referencia completa del cliente principal y de la capa de componentes de React.

Constructor

typescript
new SparkerVerify(config: {
  apiUrl: string      // URL base de la API de Sparker
  appUrl?: string     // URL base pública del frontend para enlaces de verificación
  apiKey?: string     // Clave de API para el tráfico del SDK
  timeout?: number    // Tiempo de espera para solicitudes en ms (por defecto: 30000)
})

Autenticación

MétodoDescripción
setApiKey(key)Establece o rota la clave de API para solicitudes del SDK
setAnonymousToken(token)Utiliza un token 3P en lugar de la clave de cuenta
clearApiKey()Elimina la clave de API configurada

Exportaciones de React

ComponenteDescripción
SparkerVerifiedImageEnvuelve una imagen y muestra el distintivo desplegable al pasar el cursor
SparkerCaptureFlujo de captura con registro, firma y subida integrados
@sparker-io/verify-sdk/reactPunto de entrada exclusivo de React para la capa de componentes

Ayudantes de captura en navegador

MétodoDescripción
registerBrowserDevice(name?)Crea y almacena la credencial de WebAuthn en el navegador
getStoredBrowserDevice()Devuelve los metadatos de la credencial persistida
clearStoredBrowserDevice()Borra la referencia de la credencial persistida
submitCapturedFile(file, options)Solicita nonce, firma y sube el archivo capturado en un solo paso

Métodos de verificación (autenticación opcional)

MétodoDescripción
createVerification()Crea la verificación y recibe un nonce de 5 minutos de validez
submitVerification(...)Sube el medio firmado con device_id, firma y metadatos
getVerification(id)Obtiene el estado y los detalles de la verificación

Métodos de verificación pública (sin autenticación)

MétodoDescripción
verifySignature(hash)Compara el hash de la firma contra el registro
verifyFile(file)Calcula el hash de búsqueda local y lo verifica
verifySource(url)Obtiene un recurso publicado y lo verifica del lado del cliente
verifyBatch(hashes)Verifica hasta 100 hashes simultáneamente
getVerificationDetails(id)Obtiene los detalles públicos de un registro de verificación
buildVerificationUrl(hash, src?, verificationId?)Construye la URL pública de verificación, priorizando `/verify/:id`

Ayudantes de plataforma

FunciónDescripción
computeSignedData(file, nonce)Calcula SHA-256(file + nonce) para el proceso de firma
extractWebAuthnPublicKey(response)Extrae x,y (P-256) de la respuesta de WebAuthn
buildWebAuthnCreateOptions(challenge, userId, name)Genera opciones de registro de WebAuthn
buildWebAuthnGetOptions(hash, credentialId)Genera opciones de aserción de WebAuthn
isWebAuthnAvailable()Comprueba el soporte de WebAuthn
bufferToBase64Url(buffer)Convierte ArrayBuffer a cadena base64url
base64ToBuffer(base64)Convierte cadena base64url a ArrayBuffer
sha256Hex(data)Calcula el hash SHA-256 en formato hex

Tipos

typescript
type VerificationLookupStrategy = "c2pa_signature" | "file_hash"

interface ResolvedPublicVerifyResponse {
  authentic: boolean
  verified_at: string
  lookup_hash: string
  lookup_strategy: VerificationLookupStrategy
}

interface VerificationVerifyResponse {
  id: string
  authentic: boolean
  signature_hash: string
  verified_at: string
  device: {
    name: string
    model: string
    platform: string
  } | null
  gps: GPSData | null
}

interface TokenValidateResponse {
  valid: boolean
  creator_name: string | null
  remaining_uses: number | null
  expires_at: string | null
}

Plataformas

Sparker Verify actualmente soporta la firma respaldada por hardware en navegadores web a través de WebAuthn. Los SDKs nativos para iOS y Android están planificados, pero no cuentan con soporte todavía.

Web (WebAuthn)

La plataforma web utiliza la API WebAuthn/FIDO2 para acceder al autenticador del sistema (como TouchID o Windows Hello). Las claves son de tipo ECDSA P-256 generadas en el autenticador nativo del dispositivo.

typescript
import {
  buildWebAuthnCreateOptions,
  extractWebAuthnPublicKey,
  bufferToBase64Url,
} from '@sparker-io/verify-sdk'

// Registro
const options = buildWebAuthnCreateOptions(challenge, userId, userEmail)
const credential = await navigator.credentials.create({ publicKey: options })
const response = credential.response as AuthenticatorAttestationResponse
const publicKey = extractWebAuthnPublicKey(response)

// Firma
const assertion = await navigator.credentials.get({
  publicKey: buildWebAuthnGetOptions(signedDataHash, credentialId),
})
const signature = bufferToBase64Url(
  (assertion.response as AuthenticatorAssertionResponse).signature
)
Requisitos del navegador
WebAuthn requiere un entorno seguro HTTPS (excepto en localhost). Navegadores soportados: Chrome 67+, Firefox 60+, Safari 14+, Edge 79+. Utilice isWebAuthnAvailable() para comprobar el soporte técnico.

iOS (planificado)

El registro de dispositivos y la captura nativa en iOS no están soportados todavía. Se espera que un futuro SDK para iOS utilice claves respaldadas por Secure Enclave, pero no hay un flujo activo en producción hoy en día.

Disponibilidad
Utilice el SDK web/navegador. Si planea una integración nativa en iOS, considérela como parte de su hoja de ruta en lugar de una plataforma soportada actualmente.

Android (planificado)

El registro de dispositivos y la captura nativa en Android no están soportados todavía. Se espera que un futuro SDK para Android utilice claves respaldadas por StrongBox o TEE, pero no hay un flujo activo en producción hoy en día.

Disponibilidad
Utilice el SDK web/navegador. Si planea una integración nativa en Android, considérela como parte de su hoja de ruta en lugar de una plataforma soportada actualmente.