SKS, criptografía de bolsillo
Keywords: criptografía, curva elíptica, clave pública, PGP, GPG

# SKS

## criptografía de bolsillo

### Filosofía general

Al igual que pegwit, SKS está orientado hacia la simplicidad y facilidad de uso. Por eso, el número de primitivas y opciones ha sido reducido al mínimo, posiblemente al coste de algunas funcionalidades.

Sin embargo, al contrario que pegwit, SKS sí conserva las claves públicas en un fichero que se guarda en el área de configuración del usuario. Esto se hace para elegir cómodamente las claves mediante cadenas simples que las identifiquen. Pero no hay ninguna otra funcionalidad asocidada a los "anillos de claves"; esto es:

- No se conservan claves privadas
- No hay control de confianza de las claves públicas almacenadas
- No hay certificados de revocación

Pero esto permite que, con sólo tener a mano el ejecutable y recordar la propia contraseña, uno puede usarlo en un ordenador ajeno para descifrar los mensajes que se le hayan dirigido. En contrapartida, la responsabilidad de verificar el origen de las claves recae en el propio usuario; asimismo, éste debe estar pendiente de tener a mano las claves que va a necesitar cuando no esté junto a su ordenador.

#### Recursos mínimos

SKS consume muy pocos recursos del sistema. Para hacer esto posible, el proceso de datos se hace en forma de "flujo", es decir, los datos se van procesando sobre la marcha, y por eso la memoria caché que se requiere es relativamente pequeña (en torno a 1 Mb en el escenario más exigente).

#### Implementación

La mejor forma de analizar la implementación es consultar el código fuente que se suministra. No obstante, se describen aquí brevemente algunos detalles de la misma.

Los elementos criptográficos son:

- Módulo de clave pública: curva elíptica sobre GF (2191)
- Módulo de clave simétrica: AES con clave de 192 bits en modo CTR
- Función resumen, para firmas y contraseñas: TIGER (192 bits)
- Módulo pseudoaleatorio: `/dev/urandom` en Linux-Unix y `CryptGenRandom` en Windows

### La curva elíptica

El campo está representado por polinomios en GF (2) de grado 191 (primo), esto es, GF (2191). La alternativa, que es la representación mediante Base Normal Óptima (ONB), es más rápida pero también más difícil de implementar y de revisar por terceros. En cualquier caso, la representación polinómica de SKS está muy optimizada, de modo que su tiempo de ejecución es más que razonable incluso en equipos antiguos.

El polinomio primitivo para reducir las multiplicaciones es:

s191 + s9 + 1

y la ecuación de la curva es:

y2 + xy = x3 + x2 + (s12 + s10 + s6 + s2 + 1)

Y el orden del punto fijo de la curva es un número de 190 bits —que llamaremos p—, que cumple la condición MOV hasta 100 iteraciones (lo mínimo es 9). Por tanto, la seguridad que se espera del bloque de curva elípitica es la mitad del tamaño de p, esto es, 95 bits.Todas estas constantes están definidas en los ficheros de cabecera `gflib.h`, `eclib.h`, y `eccrypt.h`.

Los puntos de la curva son parejas de polinomios (x, y) pero para su almacenamiento, SKS guarda sólo el polinomio x y un bit que decide cuál de las dos soluciones de la ecuación cuadrática para y hay que escoger.

#### Generación de claves públicas

La clave pública P se genera mediante,

P = d·Q

donde d es el multiplicador obtenido mediante el resumen de la contraseña, que se puede considerar como la clave privada, y Q es el punto fijo de la curva, que es común para todos los usuarios del sistema.

#### Cifrado

El emisor del mensaje propone, como clave común para cifrado simétrico, lo siguiente:

K = k·Q
0 < k < p

donde k es un multiplicador aleatorio, y se lo comunica al receptor mediante:

M = k·P

el cual recupera la clave simétrica, K, mediante el uso de su clave privada, d:

e = d-1 mod p
M·e = (k·P)e = (k·d·Q)e = (k·Q)d·e = K

#### Firma

SKS utiliza el algoritmo DSA de curvas elípticas (ECDSA) para generar las firmas. El algoritmo genera un par de números, (r, s) a partir de la clave privada del usuario, d, y del resumen h del mensaje que se firma, de la siguiente forma:

r = [k·Q]x mod p

donde k es un multiplicador aleatorio. Es decir, r es el resultado de convertir en número el polinomio x del producto de curva elíptica k·Q. Por otro lado:

s = k· (h + d·r )-1 mod p

El mensaje y el par (r, s) se envían al destinatario, el cual comprueba la firma calculando el resumen del mensaje, h, y tomando la clave pública del emisor, P. Entonces efectúa el siguiente cálculo:

r' = [(h·s)·Q + (r·s)·P]x mod p

si r' = r entonces se acepta la firma como válida. Esto es fácil de comprobar sustituyendo P y s en r'.

▲

### Cifrado simétrico

SKS usa el algoritmo de cifrado AES (Advanced Encryption Standard, o estándar de cifrado avanzado) con una clave de 192 bits. AES es formalmente idéntico al algoritmo Rijndael, pero con la longitud de bloque fija en 128 bits.

El modo de cifrado elegido es CTR (CounTeR, contador), que permite recuperar información incluso si se ha corrompido parcialmente el fichero y con el que no es necesario rellenar el original para ajustar su longitud a la longitud del bloque de cifrado. Se trata de cifrar un contador, del mismo tamaño que el bloque, escogido al azar. Funciona de la siguiente forma:

Ci = Mi ^ EK (S + i)

donde S es el contador, Mi, Ci el bloque original y cifrado respectivamente. EK() representa el algoritmo de cifrado para una clave dada K. El símbolo ^ representa la operación "OR exclusivo" (XOR).

El descifrado es idéntico, salvo que se invierten Mi, Ci:

Mi = Ci ^ EK (S + i)

Obsérvese que no se usa el algoritmo de cifrado inverso. En el proceso de cifrado se usa un mecanismo de autentificación HMAC para garantizar la integridad del mensaje.

▲

### Función resumen

Como se ha dicho, SKS usa el algoritmo TIGER para generar resúmenes (hash) de:

- contraseñas para generación de la clave privada,
- contraseñas para claves de cifrado convencional,
- mensajes y ficheros para firmas digitales,
- claves públicas para la creación de la huella digital.

También se usa TIGER en el módulo pseudoaleatorio.

Adicionalmente, se usa el algoritmo CRC32, de 32 bits, para obtener el identificador numérico de cada clave. Los 24 bits menos significativos del identificador se añaden a la clave cuando ésta se exporta o se genera, a modo de control de integridad.

El algoritmo TIGER goza de la confianza de la comunidad criptográfica y se considera seguro bajo cualquier punto de vista. Es muy rápido y, además, su longitud de 192 bits se adecúa a las longitudes de los multiplicadores del campo de curva elíptica. A continuación se detalla la implementación del algoritmo.

#### Generación de claves privadas

Los caracteres de la contraseña ocupan las primeras posiciones de un buffer en que previamente se han cargado 1024 bits procedentes del número Pi, que actúan a modo de "sal" para dificultar ataques de diccionario. A continuación se toma el resumen de todo el buffer y la salida se considera como un número, n, de 192 bits. La clave privada se obtiene mediante:

d = n mod p

La entropía de d, suponiendo que n tiene una entropía de 192 bits, es de 189,9 bits, muy próxima al límite teórico de 190 bits.

#### Generación de claves de cifrado convencional

A partir de la contraseña se obtiene n exactamente igual que el caso anterior. La clave de cifrado convencional se obtiene tomando otra vez el resumen de n y pasando directamente el resultado al proceso de cifrado simétrico

#### Resumen para firmas digitales

El número h se obtiene encadenando al final del fichero/texto que se desea firmar 4 octetos que representan la fecha (en colocación little endian). A continuación se obtiene el resumen del conjunto y se interpreta como un número, h', de 192 bits, de donde:

h = h' mod p

#### Huellas digitales

Se toma el resumen de la clave pública y se interpreta como un número de 192 bits, del que se muestran sus 30 cifras menos significativas en base-36.

▲

### Módulo pseudoaleatorio

SKS necesita bits aleatorios para:

1. el multiplicador que genera la clave simétrica (190 bits),
2. el multiplicador que co-genera la firma (190 bits),
3. el valor de partida del contador para el modo de cifrado simétrico CTR (128 bits).

En los casos 1. y 2. el número obtenido se toma módulo p. En el caso 3. se trunca el resultado a 128 bits.

En principio, estos bits se obtienen de un dispositivo especial del sistema. En Linux-Unix se invoca a `/dev/random` y en Windows a `CryptGenRandom()`. Para minimizar cualquier posible sesgo de estos dispositivos, se toman 1536 bits los cuales se procesan mediante TIGER para reducirlos a 192 bits.

A partir de la versión 0.92, los bits obtenidos de los dispositivos se mezclan, antes de la reducción, con el contenido de un fichero del área de usuario —`.sksprng` en Linux y `PRNG.BIN` en Windows—, si es que éste existe. Esto permite al usuario explotar sus propias fuentes de material aleatorio y usarlas en SKS, escribiendo en los ficheros mencionados hasta 1536 bits obtenidos de estas fuentes.

Si no es posible usar estos dispositivos, SKS recurre a un método estándar (ANSI C) que invoca repetidamente el reloj del sistema. Este método produce bits aleatorios de no muy alta calidad y es relativamente lento, por lo que está configurado a tomar sólo 128 bits (se puede cambiar en tiempo de compilación). Estos bits se encadenan con más material pseudoaletorio de baja calidad y se procesan varias veces mediante TIGER. El fichero fuente `entropy.c` contiene información al respecto.

▲