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.
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
| Entidad | Rol |
|---|---|
| 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
npm install @sparker-io/verify-sdk2. Envolver una imagen publicada
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.
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
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,
),
)- 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.
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.
| Plataforma | Estado | Formato de atestación | Notas |
|---|---|---|---|
| Web | Soportado hoy | webauthn | Captura desde navegador y registro de dispositivos a través de WebAuthn |
| iOS | Planificado | No soportado aún | El SDK nativo para iOS y el flujo Secure Enclave no están disponibles todavía |
| Android | Planificado | No soportado aún | El 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.
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.
// 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.
const sdk = new SparkerVerify({
apiUrl: 'https://verify.sparker.io',
appUrl: 'https://verify.sparker.io',
apiKey: 'spk_live_...',
})Comprobar soporte de WebAuthn
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.
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.
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.
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.
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
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,
)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
// 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
- El usuario abre el enlace de verificación 3P. No requiere registro ni inicio de sesión.
- El token se valida contra el servidor. Los tokens expirados o no válidos muestran un error.
- El usuario realiza la captura directamente a través de la cámara del navegador.
- La verificación queda asociada a la cuenta y cuota del creador del token.
- El contador de usos del token se incrementa. Al alcanzar los usos máximos, el token expira.
Gestionar tokens
// 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)Referencia del SDK
Referencia completa del cliente principal y de la capa de componentes de React.
Constructor
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étodo | Descripció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
| Componente | Descripción |
|---|---|
SparkerVerifiedImage | Envuelve una imagen y muestra el distintivo desplegable al pasar el cursor |
SparkerCapture | Flujo de captura con registro, firma y subida integrados |
@sparker-io/verify-sdk/react | Punto de entrada exclusivo de React para la capa de componentes |
Ayudantes de captura en navegador
| Método | Descripció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étodo | Descripció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étodo | Descripció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ón | Descripció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
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.
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
)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.
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.