Verification Methods
Endpoints para gestionar las claves criptográficas asociadas a un DID. Una clave registrada como verification method no es operativamente útil hasta que se le asocia al menos una verification relationship.
addVerificationMethod
POST /api/v1/contract/addVerificationMethod
Registra una nueva clave en el DID.
Cuerpo
| Campo | Tipo | Required | Descripción |
|---|---|---|---|
did | string | sí | DID a actualizar. |
vMethodId | string | sí | ID del verification method (base64url, 43 chars). Recomendado: thumbprint JWK. |
publicKeyType | enum | sí | secp256k1 o JsonWebKey2020. |
publicKey | string | sí | Material de clave pública en el formato correspondiente al tipo (ver nota). |
from | string | sí | EOA del controlador firmante. |
Valores de publicKeyType
La spec del enum incluye tres valores, pero solo dos están soportados operativamente. publicKeyType determina el formato del campo publicKey, no la curva: la curva real se infiere del propio material registrado.
| Valor | Soportado | Formato esperado en publicKey | Curvas válidas |
|---|---|---|---|
secp256k1 | ✅ | 64 bytes XY hexadecimales (uncompressed, sin envoltura JWK) | Solo secp256k1 |
JsonWebKey2020 | ✅ | JWK serializado como JSON y codificado en hex | Cualquier crv válido contenido en el JWK (p. ej. secp256k1, P-256) |
P-256 | ❌ | — | Reservado, devuelve 400 UNSUPPORTED |
Cómo se guarda y se resuelve
La librería del registro (@red-isbe/did-isbe-registry) reconstruye el JWK al resolver el DID con dos ramas (función vmToJwk):
- Si el
publicKeyguardado es un JWK serializado (casoJsonWebKey2020) → se devuelve tal cual. ElellipticTypeque la API asignó internamente se ignora porque el JWK ya trae su propiocrv. - Si el
publicKeyguardado son 64 bytes XY puros (casosecp256k1o material legacy) → se infiere la curva delellipticTypey se construye el JWK.
Esto significa que una clave secp256k1 puede registrarse por dos caminos distintos:
- Vía
publicKeyType: "secp256k1"— formato compacto, 64 bytes XY. - Vía
publicKeyType: "JsonWebKey2020"— envolviendo un JWK concrv: "secp256k1". Más estándar para integrar con resto de la pila JOSE.
Ambos resuelven a un verificationMethod con type: "JsonWebKey2020" y la curva correcta dentro del publicKeyJwk.
Formato de publicKey según el tipo
secp256k1— Clave pública uncompressed hexadecimal con prefijo0x04(130 chars). Ejemplo:0x04<X><Y>.JsonWebKey2020— JWK serializado como JSON string y codificado en hex. La utilidaddid-gen keys -c <curva>produce este formato directamente comoPublic Key (hex of JWK). Estructuras válidas:- P-256:
{ "kty": "EC", "crv": "P-256", "alg": "ES256", "x": "...", "y": "..." } - secp256k1:
{ "kty": "EC", "crv": "secp256k1", "x": "...", "y": "..." }
- P-256:
Ejemplo
{
"did": "did:isbe:uc:z12kVar5p6bD5WCjEJcQ18Zyt8XV",
"vMethodId": "WqpsDjTHnYVNvX8qx4a1FER8NgnEBS6DjLbDVrX-Fg4",
"publicKeyType": "JsonWebKey2020",
"publicKey": "0x7b226b7479223a224543222c22637276223a22502d323536...",
"from": "0xAe0E493C67f75381b0954644836A3C16c79D0dFD"
}
Respuesta
200 OK con la transacción sin firmar.
revokeVerificationMethod
POST /api/v1/contract/revokeVerificationMethod
Marca una clave como revocada. Las firmas hechas con ella antes de notAfter siguen siendo válidas; las posteriores no.
Cuerpo
{
"did": "did:isbe:uc:z12kVar5p6bD5WCjEJcQ18Zyt8XV",
"vMethodId": "WqpsDjTHnYVNvX8qx4a1FER8NgnEBS6DjLbDVrX-Fg4",
"notAfter": 1774700000,
"from": "0xAe0E493C67f75381b0954644836A3C16c79D0dFD"
}
| Campo | Tipo | Required | Descripción |
|---|---|---|---|
did | string | sí | DID afectado. |
vMethodId | string | sí | ID de la clave a revocar. |
notAfter | number | sí | Timestamp Unix a partir del cual la clave deja de ser válida. |
from | string | sí | EOA del controlador firmante. |
expireVerificationMethodrevoke se utiliza cuando hay compromiso de la clave; expire cuando la clave llega al final natural de su vida. Funcionalmente ambos hacen lo mismo, pero la semántica permite a los verificadores distinguir motivos.
expireVerificationMethod
POST /api/v1/contract/expireVerificationMethod
Marca una clave como expirada.
Cuerpo
{
"did": "did:isbe:uc:z12kVar5p6bD5WCjEJcQ18Zyt8XV",
"vMethodId": "WqpsDjTHnYVNvX8qx4a1FER8NgnEBS6DjLbDVrX-Fg4",
"notAfter": 2090221463,
"from": "0xAe0E493C67f75381b0954644836A3C16c79D0dFD"
}
Los campos son idénticos a revokeVerificationMethod.
rollVerificationMethod
POST /api/v1/contract/rollVerificationMethod
Rotación atómica: registra una clave nueva, programa la expiración de la antigua y define un periodo de solape.
Cuerpo
| Campo | Tipo | Required | Descripción |
|---|---|---|---|
did | string | sí | DID afectado. |
vMethodId | string | sí | ID de la nueva clave. |
publicKeyType | enum | sí | secp256k1 o JsonWebKey2020. |
publicKey | string | sí | Material de la nueva clave pública. |
notBefore | number | sí | Timestamp Unix de inicio de validez de la nueva clave. |
notAfter | number | sí | Timestamp Unix de expiración de la nueva clave. |
oldVMethodId | string | sí | ID de la clave antigua a rotar. |
duration | number | sí | Periodo de solape en segundos. Tiempo durante el cual ambas claves son válidas. |
from | string | sí | EOA del controlador firmante. |
Ejemplo
{
"did": "did:isbe:uc:z12kVar5p6bD5WCjEJcQ18Zyt8XV",
"vMethodId": "<NUEVO_THUMBPRINT>",
"publicKeyType": "JsonWebKey2020",
"publicKey": "0x<NUEVA_HEX_JWK>",
"notBefore": 1774700000,
"notAfter": 2090300000,
"oldVMethodId": "<THUMBPRINT_ANTERIOR>",
"duration": 86400,
"from": "0xAe0E493C67f75381b0954644836A3C16c79D0dFD"
}
En este ejemplo, durante 24 horas (86400 segundos) ambas claves son válidas; pasado ese tiempo, la antigua queda expirada automáticamente.
Casos de uso
- Rotación periódica de claves por política de seguridad.
- Migración de algoritmo (poco habitual; revisa compatibilidad antes).
- Reemplazo programado tras un evento que aún no compromete la clave pero recomienda cambiarla.