Ciclo de vida de las claves y flujo de firma

Keygen, firma y resharing desde el lado del cosigner.

Keygen

Crear una billetera en un workspace con un cosigner ejecuta la generación distribuida de claves entre los nodos de MPCium y tu cosigner.

  1. El orquestador envía un session_start firmado con KEYGEN, el key_id, el protocolo y el umbral.
  2. El cosigner verifica la firma y consulta a tu callback.
  3. Los participantes ejecutan el keygen de tss-lib. Cada uno termina con su propio fragmento y la clave pública compartida.
  4. El cosigner cifra su fragmento, lo almacena como shares:<protocol>:<key_id> y registra el comité.
  5. Solo la clave pública y un hash del resultado salen del cosigner.
  6. El orquestador comprueba que todas las claves públicas coincidan y las devuelve a Apex.

Las billeteras que necesitan tanto ECDSA como EdDSA ejecutan dos sesiones vinculadas. Si una falla, ambas se abortan.

Firma

Secuencia de firma: Apex hace la solicitud, el orquestador inicia la sesión, el cosigner consulta al callback, los participantes firman y el orquestador devuelve la firma
Click to open the full-size diagram

1. Admisión

Una solicitud que supera las políticas de tu workspace pasa de Apex al orquestador, firmada con la clave de iniciador de Apex. El orquestador compara el comité con el registro del keygen, confirma que todos estén en línea y envía un session_start firmado.

session_start incluye el key_id, el signing_input sin procesar, un signing_context opcional (detalles de la transacción, máximo 64 KiB), la derivation HD, el umbral y los participantes.

2. Controles locales

El cosigner rechaza la sesión a menos que se superen todos estos controles, en orden:

  1. Mensaje de menos de 128 KiB.
  2. Firma del orquestador válida (clave fijada durante el emparejamiento).
  3. Menos de 20 inicios y 10 abortos por minuto.
  4. Menos de 5 sesiones simultáneas.
  5. session_start escrito en el registro de auditoría.
  6. Tu callback devuelve approve. De lo contrario, la sesión falla con CALLBACK_REJECTED.

Si el orquestador aborta mientras el callback está pendiente, el cosigner deja de esperar.

3. Intercambio de claves

  • La sesión debe coincidir con el comité fijado: umbral, claves de las partes, claves de identidad y flags de aprobador.
  • El cosigner envía peer_joined, peer_ready y una clave X25519 firmada a cada peer.
  • Cada par de peers obtiene una clave ChaCha20-Poly1305 por dirección (HKDF sobre X25519, vinculada a la sesión).

4. Firma de umbral

El orquestador envía mpc_begin. Si la billetera tiene un aprobador (por ejemplo, un aprobador móvil de Fystack), mpc_begin debe incluir su aprobación firmada de este signing input exacto. Sin ella, el cosigner hace fallar la sesión con APPROVAL_REQUIRED.

Luego, los participantes ejecutan las rondas de tss-lib. Cada mensaje está firmado y numerado en secuencia, por lo que se descartan los reenvíos.

5. Resultado

Cada participante informa un hash de su firma. El orquestador exige que todos los hashes coincidan y luego devuelve el resultado firmado (signature, r, s, recovery id) a Apex. El cosigner registra session_end y elimina su checkpoint.

Resharing

Reemplaza los fragmentos, opcionalmente con un nuevo comité o umbral. La clave pública y las direcciones no cambian.

  1. El comité y el umbral anteriores provienen del registro del keygen, no de quien hace la llamada.
  2. Al menos threshold + 1 miembros anteriores deben estar en línea.
  3. Los miembros anteriores y nuevos ejecutan el resharing de tss-lib. Los fragmentos nuevos quedan preparados; los anteriores siguen activos.
  4. Todos los participantes informan el mismo resultado y una clave pública sin cambios.
  5. El orquestador persiste la decisión y luego envía un reshare_commit firmado. Cada participante reemplaza su fragmento por el nuevo.

Abortar antes del commit conserva los fragmentos anteriores. Después del commit solo se avanza: el commit se reintenta hasta que todos los participantes lo confirmen, incluso después de una caída.

Códigos de error

Código Significado
CALLBACK_REJECTED El callback rechazó la solicitud, agotó el tiempo de espera o devolvió una respuesta inválida.
APPROVAL_REQUIRED Falta la aprobación firmada del aprobador de la billetera.
UNAVAILABLE Un participante estaba desconectado al enviar la solicitud.
PARTICIPANT_FAILED Un participante informó un error. Consulta failure_reason.
PARTICIPANT_DISCONNECTED El stream de un participante se cortó a mitad de la sesión.
SESSION_TIMEOUT No se completó en 120 segundos.
RESULT_HASH_MISMATCH Los participantes no coincidieron en el resultado.
CONFLICT Hay otra sesión en curso para esta billetera y protocolo.