Skip to content
← Todas las publicaciones
· Delta1 Labs LicenciamientoSeguridadAnálisis a fondo

Anatomía de una clave de licencia firmada: por qué no se puede falsificar

Una buena clave de licencia no es una cadena aleatoria cotejada contra una lista — es un payload de claims firmado que la app puede verificar sin conexión con una clave pública que distribuye. Aquí tienes qué vive dentro de una clave firmada, por qué la división privada/pública la hace infalsificable, cómo funciona la verificación sin servidor, y qué protege y qué no la firma.

Pregunta a alguien cómo funcionan las claves de licencia y a menudo oyes «la app envía la clave a un servidor, el servidor comprueba si es válida». Ese diseño existe, pero tiene una dependencia dura: sin servidor, sin validación. Un mejor diseño hace la clave autoprobatoria — lleva sus propios claims y una firma criptográfica, y la aplicación la verifica sin conexión con una clave pública que ya distribuye. Nada de la autenticidad depende de una llamada de red. Entender qué vive dentro de tal clave, y por qué no se puede falsificar, es el cimiento de todo esquema de licenciamiento robusto.

Una clave es un payload de claims firmado

Una clave de licencia moderna no es un identificador aleatorio; es un pequeño conjunto de claims más una firma sobre esos claims. Los claims son los hechos que la licencia afirma:

{
  "product": "acme-pro",
  "tier": "enterprise",
  "licensee": "acct_8f21",
  "seats": 25,
  "expiry": "2027-10-04T00:00:00Z",
  "features": ["sso", "audit-log"]
}

Por sí solo, ese payload es solo datos — cualquiera podría teclearlo. Lo que lo hace una licencia es la firma añadida: un valor calculado a partir del payload con una clave privada que solo tu servidor de licencias tiene. La clave que tu cliente pega es el payload y la firma juntos, codificados en una forma compacta y pegable.

La división privada/pública es todo el truco

La razón por la que la clave no se puede falsificar es la criptografía asimétrica. Hay dos claves, y no son intercambiables:

  • La clave privada vive solo en tu servidor de licencias. Es lo único que puede producir una firma válida.
  • La clave pública está embebida en tu aplicación, distribuida a cada cliente. Puede verificar una firma pero no puede producir una.

Derivar la clave privada de la pública es computacionalmente inviable para los algoritmos usados (como Ed25519 o ECDSA sobre P-256). Así que un atacante que tiene tu aplicación — y por tanto tiene la clave pública — aún no puede firmar nada. Puede leer la clave pública todo el día; no le ayuda a acuñar una nueva clave ni a alterar una existente, porque la verificación fallará en cuanto un solo byte del payload o de la firma cambie.

Aquí está la forma de firmar en el servidor y verificar en la app, usando Ed25519:

// SERVER (private key never leaves here): sign the canonical claims bytes.
byte[] payload = CanonicalJson(claims);                 // stable byte encoding
byte[] signature = SignEd25519(payload, privateKey);     // 64-byte signature
string licenseKey = Base32(Concat(payload, signature));  // what the customer gets
// APP (ships only the public key): verify before trusting any claim.
var (payload, signature) = SplitBase32(licenseKey);
if (!VerifyEd25519(payload, signature, PublicKey))        // embedded public key
    throw new InvalidLicenseException("signature invalid");

var claims = ParseClaims(payload);
if (claims.Product != "acme-pro") throw new InvalidLicenseException("wrong product");
// expiry, tier, seats, features are now trustworthy — they were signed

El orden importa: verifica la firma primero, luego lee los claims. Un claim que no has verificado es entrada controlada por el atacante. Una vez que VerifyEd25519 devuelve true, cada campo del payload se sabe que es exactamente lo que tu servidor firmó — sin cambios y auténtico.

Servidorsign(claims, priv)clave de licenciaclaims + firmacadena pegableApp (embebe clave pública)1. verify(sig, pub) → ¿ok?2. luego confía tier / caducidad / asientos

Por qué autocontenida vence a «cotejar contra una lista»

Como los claims y la firma viajan juntos y la clave pública ya está en la app, la verificación es enteramente local. No se necesita viaje de ida y vuelta al servidor para saber que una clave es auténtica y no modificada — que es lo que hace posible la verdadera activación en entornos aislados y sin conexión. Un diseño de lista en servidor no puede hacer esto: debe alcanzar el servidor en cada comprobación, así que una máquina sin conexión, un parpadeo de red o un endpoint de validación retirado se convierten todos en caídas para clientes que pagan.

Las claves autocontenidas también escalan trivialmente. No hay fila de base de datos que buscar por validación ni endpoint que mantener en línea para la autenticidad; las matemáticas son la autoridad. También puedes contactar un servidor periódicamente — para honrar la revocación o refrescar un lease — pero eso es una mejora encima de una clave que ya es demostrablemente genuina, no un prerrequisito para confiar en ella.

Cómo se ve una clave falsificada o manipulada

Considera las dos cosas que un atacante podría intentar. Alterar un claim — subir tier a enterprise o empujar expiry una década adelante — cambia los bytes del payload, así que la firma ya no coincide y VerifyEd25519 devuelve false. Fabricar una clave entera requiere producir una firma que verifique contra tu clave pública, lo que requiere la clave privada que no tienen. Ambas fallan en la misma comprobación. Esta es la evidencia de manipulación que un diseño de cadena-aleatoria-más-base-de-datos carece: ahí, la cadena no lleva claims, así que el servidor es lo único que sabe qué significa la clave, y la clave en sí no prueba nada.

Detalles prácticos que importan

Unos pocos específicos separan un juguete de un esquema de producción:

  • Codificación canónica. Firma una representación en bytes estable de los claims, y verifica sobre los bytes exactos recibidos. Si tu serializador JSON reordena campos o varía el espacio en blanco entre firmar y verificar, las claves válidas fallarán. Una forma canónica (orden de campos fijo, sin espacio en blanco incidental) evita esto.
  • Rotación de claves. Con el tiempo querrás rotar la clave de firma. Distribuye la app capaz de aceptar más de una clave pública — la actual más predecesoras recientes — para que las claves firmadas antes de una rotación sigan verificando. Hornea esto desde el día uno; añadirlo después es doloroso.
  • Algoritmo moderno, tamaño adecuado. Prefiere Ed25519 o ECDSA P-256 sobre opciones heredadas; dan firmas y claves cortas con seguridad fuerte. Evita hacer tu propia firma o usar un MAC simétrico en el cliente (ver abajo).
  • Codifica para humanos donde se teclean claves. Si los clientes pegan claves a mano, una forma base32 agrupada (XXXX-XXXX-…) con un checksum atrapa erratas antes de que la verificación siquiera corra.

Qué no hace la firma

La firma es el cimiento, no todo el edificio. Dos límites que dejar claros. Primero, una firma prueba autenticidad, no exclusividad — una clave firmada es genuina sin importar cuántas personas la copien, así que firmar no hace nada por detener la compartición. Ese es el trabajo de la activación y la vinculación de dispositivo, puestas encima. Segundo, nunca pongas el secreto de firma en el cliente. Todo el esquema descansa en que la capacidad de firma sea solo-servidor; si «simplificas» usando un secreto simétrico (una clave HMAC) embebido en la app para que la app pueda firmar y verificar, entonces cualquiera que extraiga ese secreto — y se puede extraer — puede falsificar claves ilimitadas. La firma asimétrica existe precisamente para que el cliente tenga solo el poder de verificar, nunca de crear.

En conjunto, una clave de licencia firmada es una credencial pequeña y autoprobatoria: claims que tu servidor avaló, envueltos en una firma que solo tu servidor pudo producir y cualquier copia de tu app puede comprobar sin red. Acierta ese cimiento — verifica antes de confiar, mantén la clave privada del lado del servidor, planea la rotación — y todo lo demás en el licenciamiento (caducidad, derechos, activación, revocación) se construye sobre terreno que no pueden falsificar bajo tus pies.

Prueba Nebula.NET

Endurece tu código .NET en minutos — empieza con la edición gratuita.