Materia : Criptografía y Seguridad Informática (66-69 ...

76
U.B.A Facultad de Ingenieria Materia : Criptografía y Seguridad Informática (66-69) Integrantes: Requejo, Javier (70.722) Boaglio, Cristian Alfredo (71.342)

Transcript of Materia : Criptografía y Seguridad Informática (66-69 ...

U.B.AFacultad de Ingenieria

Materia : Criptografía y Seguridad Informática (66-69)

Integrantes: Requejo, Javier (70.722)

Boaglio, Cristian Alfredo (71.342)

Criptografía y Seguridad

Informática

Pretty Good Privacy Página1

Contenido.

Introducción 2

Mas sobre PGP 7

Los principales algoritmos de PGP

RSA 8IDEA 10MD5 11SHA 13

Ataques a PGP 28

Manual de referencia PGP 5.0 32

Código fuente de los principales algoritmos del PGP

RSA 40 IDEA 46 MD5 59 SHA 65

Referencias 75

Criptografía y Seguridad

Informática

Pretty Good Privacy Página2

Introducción.

Fundamentos del cifrado

Supóngase que desea enviar un mensaje a una colega, a quien llamaremos Alicia, y no desea quenadie más que Alicia sea capaz de leerlo. Como es mostrado en la Figura 1, usted puede encriptar o cifrarel mensaje, lo que significa desorganizarlo de una manera complicada, haciéndolo ilegible para cualquieraexcepto usted y Alicia. Usted usa una clave criptográfica para cifrar el mensaje, y Alicia debe usar lamisma clave para descifrarlo o desencriptarlo. Es usada una clave única para el cifrado y el descifrado.Esto significa que esta clave debe ser transmitida inicialmente por medio de canales de comunicaciónseguros de modo que ambas partes puedan conocerla antes que los mensajes cifrados sean enviados porcanales inseguros. Esto puede ser un inconveniente.

Cómo funciona la criptografía de clave pública

En la criptografía de clave pública, como es mostrado en la Figura 2, todos tienen dos clavescomplementarias relacionadas, una clave pública y una clave privada. Cada clave destraba el código quegenera la otra clave. Conocer la clave pública no lo ayuda a deducir la clave privada correspondiente. Laclave pública puede ser publicada y distribuida ampliamente a través de una red de comunicaciones.

Este protocolo proporciona privacidad sin la necesidad de los canales seguros que requiere lacriptografía de clave secreta convencional.

Cualquiera puede usar la clave pública del destinatario para cifrar un mensaje a esa persona, y eldestinatario usa su propia clave privada correspondiente para descifrar ese mensaje. Nadie más que el

Criptografía y Seguridad

Informática

Pretty Good Privacy Página3

destinatario puede descifrarlo, porque nadie más tiene acceso a esa clave privada. Ni siquiera la personaque cifró el mensaje con la clave pública del destinatario puede descifrarlo.

Cómo se cifran archivos y mensajes

Debido a que el algoritmo de cifrado con clave pública es mucho más lento que el cifradoconvencional de clave única, se logra un mejor cifrado usando el proceso mostrado en la Figura 3.

Para cifrar el mensaje es usado un algoritmo rápido y de alta calidad de cifrado convencionalmediante clave secreta. El mensaje original sin cifrar es llamado "texto llano". En un proceso invisiblepara el usuario, una clave aleatoria temporal creada solamente para esta "sesión", es usada para cifrarconvencionalmente el archivo de texto llano. Luego es usada la clave pública del destinatario para cifraresta clave convencional aleatoria temporal. Esta "clave de sesión" convencional, cifrada mediante clavepública, es enviada junto con el texto cifrado al destinatario.

Los algoritmos simétricos de PGP

PGP ofrece una selección de diferentes algoritmos de clave secreta para cifrar el mensaje real.Cuando decimos algoritmo de clave secreta, nos referimos a un sistema de cifrado en bloqueconvencional, o simétrico, que usa la misma clave para cifrar y descifrar. Los tres cifrados en bloquesimétricos ofrecidos por PGP son CAST, Triple-DES e IDEA.

Los tres métodos de cifrado operan en bloques de 64 bits de textos llano y cifrado. Las clavesCAST e IDEA tienen un tamaño de 128 bits, mientras que Triple-DES usa una clave de 168 bits. Al igualque la Norma de Cifrado de Datos [DES, Data Encryption Standard], cualquiera de estos tres métodospueden ser usados en los modos de Realimentación de Cifrado [CFB, Cipher Feedback] y de Encadenadode Bloques de Cifrado [CBC, Cipher Block Chaining]. PGP los usa en modo CFB de 64 bits.

Se ha incluido el algoritmo de cifrado CAST en PGP porque promete ser un buen sistema decifrado en bloques con una clave de 128 bits, es muy rápido, y es gratuito. Su nombre se deriva de lasiniciales de sus autores, Carlisle Adams y Stafford Tavares, de la empresa Northern Telecom (Nortel). Eldiseño está basado en una aproximación muy formal, con un cierto número de afirmaciones formalmentedemostrables, exhibiendo buenas razones para creer que probablemente se necesite agotar todas lascombinaciones posibles para destrabar su clave de 128 bits. CAST no tiene claves débiles o semidébiles.Hay fuertes argumentos acerca que CAST es completamente inmune a los criptoanálisis lineal ydiferencial, las dos formas de criptoanálisis más potentes conocidas en la literatura del tema y que hansido muy eficaces para burlar el DES.

El cifrado en bloque IDEA (International Data Encryption Algorithm, Algoritmo de Cifrado deDatos Internacional), está basado en el concepto de diseño de "mezclar operaciones desde gruposalgebraicos diferentes". Fue desarrollado en la ETH de Zurich por James L. Massey y Xuejia Lai, y

Criptografía y Seguridad

Informática

Pretty Good Privacy Página4

publicado en 1990. Trabajos publicados anteriormente sobre el algoritmo lo llamaban IPES (ImprovedProposed Encryption Standard, Norma de Cifrado Mejorada Propuesta), pero posteriormente le cambiaronel nombre a IDEA. Hasta ahora, IDEA ha resistido mucho mejor los ataques que otros métodos decifrado. Además IDEA es mucho más resistente que DES al ataque altamente exitoso mediantecriptoanálisis diferencial de Biham y Shamir, así como ataques de criptoanálisis lineal. El mayorobstáculo para la aceptación de IDEA como una norma ha sido el hecho de que Ascom Systec tiene unapatente sobre su diseño y, a diferencia de DES y CAST, IDEA no ha sido puesto libre de derechos adisposición de cualquiera.

Como una protección, PGP incluye Triple-DES de tres claves en su repertorio de cifrados enbloque disponibles. DES fue desarrollado por IBM a mediados de los setenta. Aunque tiene un buendiseño, su tamaño de clave de 56 bits es demasiado pequeño para los patrones de hoy. Triple-DES es muyfuerte y ha sido bien estudiado por muchos años, así que podría ser una apuesta más segura que loscifrados más nuevos como CAST e IDEA. Triple-DES es el DES aplicado tres veces al mismo bloque dedatos, usando tres claves diferentes, excepto que la segunda operación DES se hace marcha atrás, enmodo de descifrado. Si bien Triple-DES es mucho más lento que CAST e IDEA, usualmente la velocidadno suele ser algo crítico para aplicaciones de correo electrónico. Aunque Triple-DES usa un tamaño declave de 168 bits, parece tener una fortaleza efectiva de al menos 112 bits frente a un atacante con unacapacidad de almacenamiento de datos imposiblemente inmensa para usar en el ataque.

Las claves públicas PGP que fueron generadas por PGP versión 5.0 o posterior incluyen dentrode sí información que cuenta a un remitente qué métodos de cifrado en bloque son comprendidos por elsoftware del destinatario, de modo que el software del remitente sepa qué método de cifrado puede serusado para cifrar. Las claves públicas DSS/Diffie-Hellman aceptan CAST, IDEA o Triple-DES comométodos de cifrado en bloque, con CAST como opción predeterminada. De momento, por razones decompatibilidad, las claves RSA no permiten esta selección. PGP solamente usa cifrado IDEA para enviarmensajes con claves RSA, ya que las versiones más antiguas de PGP aceptan solamente RSA e IDEA.

Compresión de datos

PGP normalmente comprime el texto llano antes de cifrarlo porque sería demasiado tarde hacerlodespués: los datos cifrados no son comprimibles. La compresión de datos ahorra tiempo de transmisiónpor módem, espacio de disco, y lo que es más importante, fortalece la seguridad del cifrado. La mayoríade las técnicas de criptoanálisis explotan las redundancias que se encuentran en el texto llano, paraquebrar el cifrado. La compresión de datos reduce esta redundancia en el texto llano, aumentandograndemente con ello la resistencia al criptoanálisis. Se necesita un tiempo extra para comprimir el textollano, pero desde el punto de vista de la seguridad vale la pena.

Los archivos demasiado cortos para comprimir, o que simplemente no se comprimen bien, no soncomprimidos por PGP. Además, el programa reconoce los archivos producidos por la mayoría de losprogramas populares de compresión, tales como PKZIP, y no intenta comprimir un archivo que ya ha sidocomprimido.

El programa usa las rutinas de compresión ZIP de dominio público escritas por Jean-Loup Gailly,Mark Adler y Richard B. Wales. Este software ZIP usa algoritmos de compresión que sonfuncionalmente equivalentes a los usados por PKZIP 2.x de PKWare. Este software de compresión ZIPfue seleccionado para PGP fundamentalmente porque tiene una tasa de compresión realmente buena yporque es rápido.

Acerca de los números aleatorios usados como claves desesión.

PGP utiliza un generador de números pseudoaleatorios criptográficamente fuerte para crearclaves de sesión temporales. Si el archivo de números aleatorios no existe, es creado automáticamente yalimentado con números verdaderamente aleatorios derivados de sus eventos aleatorios recogidos por elprograma PGP a partir de los tiempos entre pulsaciones de teclado y movimientos del ratón.

Este generador recarga el archivo de números aleatorios cada vez que es usado, mezclandomaterial nuevo derivado parcialmente de la hora del día con otras fuentes verdaderamente aleatorias. Usael algoritmo de cifrado convencional como un motor para el generador números aleatorios. El archivo de

Criptografía y Seguridad

Informática

Pretty Good Privacy Página5

números aleatorios contiene material generado aleatoriamente y material de clave aleatorio usado para laclave convencional de sesión.

Este archivo de números aleatorios debería estar protegido para evitar que sea descubierto, y asíreducir el riesgo que un atacante deduzca sus claves de sesión siguiente o anterior. El atacante tendría queesforzarse para obtener algo útil a partir de este archivo de números aleatorios, porque el archivo eslavado criptográficamente antes y después de cada uso.

Cómo funciona el descifrado

Como es mostrado en la Figura 4, el proceso de descifrado es simplemente el opuesto al cifrado.La clave privada del destinatario es usada para recuperar la clave de sesión temporal, y luego esa clave desesión es usada para activar el algoritmo de clave secreta convencional rápido para descifrar el verdaderomensaje cifrado.

Cómo funciona la firma digital

PGP usa firmas digitales para autenticar mensajes. La propia clave privada del remitente puedeser usada para cifrar un condensado del mensaje, "firmando" así el mensaje. Un condensado de mensaje[message digest] es una función hash [resumen del mensaje], unidireccional, criptográficamente fuerte, de160 o 128 bits. Es análogo a una "suma de control" [checksum] o a un código de control de errores CRC[Cyclic Redundancy Checksum, Suma de Control de Redundancia Cíclica], en el sentido que representade modo compacto el mensaje y es usado para detectar cambios en el mismo. Sin embargo, a diferencia deCRC, se cree que es computacionalmente inviable que un atacante consiga hacer un mensaje substitutoque produzca un condensado de mensaje idéntico. El condensado de mensaje se cifra con la clave privadadel remitente, creando una firma digital del mensaje.

La Figura 5 muestra cómo es generada una firma digital.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página6

El destinatario (o cualquier otro) puede verificar la firma digital usando la clave públicadel remitente para descifrarla, como es mostrado en la Figura 6. Esto comprueba que fue el remitentequien verdaderamente originó del mensaje, y que el mensaje no ha sido alterado posteriormente por nadie,porque solamente el remitente posee la clave privada que hizo esa firma. No es posible la falsificación deun mensaje firmado, y el remitente no puede más tarde negar que lo firmó.

Acerca del condensado de mensaje

El condensado de mensaje es un "destilado" compacto (160 bits o 128 bits) del mensaje o unasuma de control del archivo. Usted puede imaginarlo como una "huella dactilar" del mensaje o archivo.El condensado del mensaje "representa" su mensaje de tal modo, que si de alguna manera el mensaje fueraalterado, resultaría un condensado de mensaje diferente. Esto hace posible detectar cualquier cambiohecho al mensaje por un falsificador. Un condensado de mensaje es calculado usando una función hashunidireccional, criptográficamente fuerte. Debería ser computacionalmente inviable para un atacanteconstruir un mensaje substituto que produjese un condensado de mensaje idéntico. A este respecto, uncondensado de mensaje es mucho mejor que una suma de control [CRC], porque es fácil hacer un mensajediferente que produzca la misma suma de control. Pero, al igual que una suma de control, usted no puedededucir el mensaje original partiendo del condensado de mensaje.El algoritmo para el condensado de mensaje usado en PGP (versión 5.0 y posterior) es llamado SHA[Secure Hash Algorithm, Algoritmo Hash Seguro], diseñado por la NSA para el Instituto Nacional de

Criptografía y Seguridad

Informática

Pretty Good Privacy Página7

Normas y Tecnología, NIST [National Institute of Standards and Technology]. SHA es un hash de 160bits.

Asimismo, el SHA ha sido publicado sin limitaciones y ha sido extensamente revisado por lamayoría de los mejores criptógrafos del mundo que se especializan en funciones de fragmentosmezclados, y la opinión unánime es que SHA está extremadamente bien diseñado. Tiene algunasinnovaciones de diseño que corrige todas las debilidades observadas en los algoritmos de condensado demensaje publicados previamente por los criptógrafos académicos. Todas las nuevas versiones de PGPusan SHA como algoritmo de condensado de mensaje para crear firmas con las nuevas claves DSS quecumplen la Norma de Firma Digital [Digital Signature Standard] del NIST. Por razones decompatibilidad, las nuevas versiones de PGP todavía usan MD5 para las firmas RSA, porque era lo usadopor las versiones más antiguas de PGP.

El algoritmo de condensado de mensaje usado por las versiones más antiguas de PGP es elAlgoritmo de Condensado de Mensaje [Message Digest Algorithm] MD5, puesto a disposición en elpúblico por RSA Data Security, Inc. MD5 es un algoritmo hash de 128 bits. En 1996 casi fue quebrado elMD5 por un criptógrafo alemán, Hans Dobbertin. Aunque en ese momento el MD5 no fue quebradocompletamente, se descubrió que tiene tan serias debilidades que nadie debería seguir usándolo paragenerar firmas. Trabajos ulteriores en este campo podrían quebrarlo completamente, permitiendo que lasfirmas sean falsificadas.

Mas sobre PGP.

PGP es un paquete completo de seguridad para correo electrónico. Presta servicios deencriptación, autenticación, firmas digitales y compresión de datos. Todo el paquete se distribuye deforma gratuita, incluyendo el código fuente. Es posible conseguir PGP en Internet para varias plataformasincluídas Unix, Windows y MacOS.Debido a las restricciones impuestas por el gobierno de los Estados Unidos a la exportación de sistemasde encripción, PGP ha sido el foco de diversas controversias. Además de otros conflictos con relación apatentes del algoritmo RSA.

PGP utiliza algoritmos existentes de encripción, en vez de crear unos propios. Estosalgoritmos son:

RSA, IDEA y MD5. También PGP soporta compresión de texto, utilizando el algoritmo ZIP. Para enviar un mensaje encriptado y firmado, ambas partes deben tener el

software PGP e intercambiar sus llaves públicas. El proceso es el siguiente:Supongamos que Alice quiere enviar un mensaje firmado a Bob de forma segura (encriptado). TantoAlice como Bob tienen llaves privadas (Dx) y llaves públicas (Ex). Es necesario que ambas partesconozcan la llave pública del otro.

Alice empieza su programa PGP en su computador. PGP aplica un algoritmo de hash al mensajeen texto plano (P), este algoritmo es MD5. Se concatena P con el hash y se obtiene P1. El resultado escomprimido con el conocido algoritmo Ziv Lempel, obteniéndose P1.Z. Ahora Alice escoge una frase queserá utilizada por el programa PGP para generar una llave aleatoria, dependiendo del texto escrito y lavelocidad de escritura, se Obtiene Km, esta llave se utiliza para encriptar P1.Z con el algoritmo IDEA,Km a su vez es encriptada con la llave pública RSA de Bob. Se concatena la llave Km encriptada con elresultado del algoritmo IDEA y finalmente se convierte a Base 24. El mensaje a transmitir por la red solocontiene caracteres alfabéticos, dígitos y los caracteres +, / e =.

Cuando Bob recibe el mensaje, revierte la codificación Base 24 y desencripta la llave IDEA(Km) utilizando su llave RSA privada. Utilizando Km llega a P1.Z. Luego de decomprimirlo, separa eltexto plano del hash encriptado, desencripta el hash con la llave pública de Alice, Bob aplica el algoritmode MD5 al texto plano y lo compara con el hash que obtuvo al utilizar la llave pública de Alice, si soniguales, se puede estar completamente seguro de que el mensaje no fue alterado y que quien lo envió fueefectivamente Alice.

RSA es un algoritmo lento, pero solamente es utilizado en dos pasos: para encriptar el hash MD5y para encriptar la llave IDEA. La encripción más pesada es llevada a cabo por IDEA que es más rápidoque RSA.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página8

Un mensaje PGP se muestra en la siguiente figura:

La parte de la firma contiene un encabezado. Al encabezado le sigue una estampilla de tiempo, elidentificador para la llave pública del que envía que puede ser utilizado para desencriptar el hash, algunainformación que identifica los algoritmos utilizados (tipos) y el hash mismo. La parte del mensajetambién contiene un encabezado, el nombre del archivo por defecto en caso que el receptor quieragrabarlo en el disco, la hora de creación del mensaje y finalmente el mensaje mismo.El manejo de llaves en PGP se hace mediante llaveros. Un usuario puede tener varios pares de llaves para él, para permitir cambiarlas en caso de que sospeche que una llave ya no es segura, peropermitiendo que los mensajes enviados recientemente puedan ser reconocidos. Estas llaves están en elllavero de llaves privadas, que está protegido mediante una frase clave, en caso de que sea robado.

Un usuario tiene un llavero de llaves públicas, donde almacena las llaves públicas de susamigos y de aquellos con quien intercambiar correspondencia.Se usa también para enviar ficheros a través de correo electrónico codificados en formato ascii y muchomejor que otros sistemas ya que el PGP usa antes de codificar una compresión zip, como se indicóanteriomente, al documento o programa que va a codificar.

Los principales algoritmos de PGP.

EL algoritmo RSA

La siguiente descripción detalla el algoritmo RSA:

1. Se toman dos números P y Q que sean primos y de unos 1024 bits.

2. Se toma un número E, de tal manera que:

E < (P.Q)=NE y (P-1).(Q-1) no tienen factores primos comunesE es imparE no tiene que ser primo

Este número E formará junto con N la clave pública para encriptar.

3. Se calcula un número D que cumpla que (D.E)-1sea divisible por (P-1).(Q- 1).Este número D será la clave privada para desencriptar.

4. Para encriptar un texto se procede como sigue: el texto T queda codificado en unnúmero M. A cada letra o símbolo del alfabeto se le asigna un número decimal o binario

Criptografía y Seguridad

Informática

Pretty Good Privacy Página9

(Ej: A=01,B=02,...,Z=26, espacio en blanco 00). Así, cualquier texto se le asigna unnúmero y un número corresponde a un texto.Este número M se subdivide en bloques Mi de tamaño j o j-1 de forma que, según sea elalfabeto usado el decimal o el binario cumpla en cada caso 10 ^ (j-1) < n < 10 ^ j ó 2^ (j-1) < n < 2 ^ j. Si el tamaño es j, puede que el descifrado no sea único.Se encripta Mi en Ci con la función

Ci = (Mi^E) mod N

donde Mi es el entero positivo a encriptar.

5. La función de desencriptado es:

Ti = (Ci^D) mod N

donde Ci es el texto encriptado como entero positivo.

La clave pública es el par (N, E). La clave privada es el número D. En principio, no se conocenmétodos por los que sea fácil calcular D, P o Q, dados solamente (N, E), y dado que P y Q sonnúmeros de 1024 bits, no existe todavía una computadora lo suficientemente potente para sacar todoslos factores de N y probar combinándolos. Sin embargo, hay que tener en cuenta que no está probadodel todo que no exista ese método, o que no pueda conseguirse dentro de unos años. Tampoco estáprobado que la única manera de romper el algoritmo RSA sea sacando los factores de N.Vamos a ver un ejemplo: el texto a encriptar es ES SECRETO.

1. Se eligen los números primos P = 11 y Q = 17. N = 187.

2. (P-1)*(Q-1) = 10*16 = 160. Tomamos D = 7, pues m.c.d (7,160) = 1. 3. E = 23, pues 23*7= 161 = 1 (mod 160). 4. Clavepública (23,187) 5. Encriptamos el mensaje: Espacio en blanco = 00; A = 01; B = 02; C = 03; D =04;E = 05; F = 06; G = 07; H= 08; I= 09; J=10; K=11; L=12; M=13; N=14; Ñ=15; O=16; P=17; Q=18;R=19; S=20; T=21; U=22; V=23; W=24; X=25; Y=26; Z=27.

El texto sería: 05200020050319052116.

Determinamos j = 3, pues 100 < 187 < 10000. Tomamos j-1 = 2. El texto queda subdivido en:05 2000 20 05 03 19 05 21 16 (M1=05, M2=20, etc.)

C1 = 05^23 (mod 187) = 180C2 = 20^23 (mod 187) = 113C3 = 00^23 (mod 187) = 000C4 = 20^23 (mod 187) = 113C5 = 05^23 (mod 187) = 180C6 = 03^23 (mod 187) = 181C7 = 19^23 (mod 187) = 094C8 = 05^23 (mod 187) = 180C9 = 21^23 (mod 187) = 098C10 = 16^23 (mod 187) = 169

El texto cifrado queda:

180 113 000 113 180 181 094 180 098 1696. El receptor del mensaje podría recuperar el texto original de la siguiente manera:M1 = 180^7(mod 187) = 05 = EM2 = 113^7 (mod 187) = 20 = SM3 = 000^7 (mod 187) = 00 =M4 = 113^7 (mod 187) = 20 = S

Criptografía y Seguridad

Informática

Pretty Good Privacy Página10

M5 = 180^7 (mod 187) = 05 = EM6 = 181^7 (mod 187) = 03 = CM7 = 094^7 (mod 187) = 19 = RM8 = 180^7 (mod 187) = 05 = EM9 = 098^7 (mod 187) = 21 = TM10 = 169^7 (mod 187) = 16 = O

EL ALGORITMO IDEA

El algoritmo de clave única IDEA (International Data Encryption Algorithm) es uncifrador de bloques que utiliza texto en bloques de 64 bits y una clave de 128 bits de longitud paraproducir bloques de salida cifrados de 64 bits. Ha sido diseñado de tal manera que el proceso deencriptado consiste en ocho vueltas de cifrado que son idénticas excepto en que usan diferentessubclaves de la clave de 128 bits, terminando con una transformación de la salida. En cada vuelta seutilizan tres operaciones:

• suma bit a bit• multiplicación bit a bit• OR exclusivo.

Se crean para cada vuelta de encriptado seis subclaves de 16 bits cada una, de la clave de128 bits, además de otras cuatro para la transformación final. El proceso para crearlas es el siguiente:

1. La clave de 128 bits es dividida en ocho claves de 16 bits, que serán las ocho primerassubclaves.

2. La clave de 128 bits es desplazada 25 posiciones a la izquierda para obtener una nuevaclave, que vuelve a ser dividida en ocho claves, que serán las siguientes ochosubclaves. Este proceso se repite hasta obtener las 52 subclaves.

En la primera vuelta de cifrado, el bloque de texto de 64 bits se divide en cuatro bloquesde 16 bits, ya que todas las operaciones se harán con números de 16 bits. Se comienza combinandolas cuatro primeras subclaves con dos de los bloques de texto sumándolos bit a bit, y con los otrosdos multiplicándolos bit a bit. Por último, se realiza el OR exclusivo entre los bloques resultado delas operaciones anteriores y otras dos subclaves. Así, al final de la primera vuelta se obtienen cuatrobloques que serán las entradas de la segunda vuelta con el orden cambiado parcialmente. En cadavuelta se usan 6 subclaves.

Este proceso se repite en cada una de las siete siguientes vueltas utilizando diferentessubclaves. Para terminar, los cuatro bloques resultado de la octava vuelta son combinados con lasúltimas cuatro subclaves que quedan sin utilizar sumándolos y multiplicándolos bit a bit,obteniéndose finalmente cuatro bloques de 16 bits de texto encriptado que forman el bloque de salidade 64 bits. En ningún punto del proceso de encriptado se usan contiguamente dos operacionesiguales.

El proceso de desencriptado es prácticamente el mismo que el de encriptado, con ladiferencia de que las 52 subclaves son las inversas de las empleadas en el encriptado respecto de laoperación en la que fueron usadas, además de utilizarse en el orden inverso.

A continuación se detalla el proceso explicado previamente:El bloque de dato de 64 bits (datos originales) es dividido en cuatro segmentos de 16 bits

cada uno, que son llamados p1, p2, p3, p4. Las subclaves son definidas como s1, s2, s3, s4, ... , s52.En cada vuelta de encriptado se realizan los siguientes pasos:

• p1 * s1 -> d1• p2 + s2 -> d2• p3 + s3 -> d3• p4 * s4 -> d4• d1 XOR d3 -> d5• d2 XOR d4 -> d6

Criptografía y Seguridad

Informática

Pretty Good Privacy Página11

• d5 * s5 -> d7• d6 + d7 -> d8• d8 * s6 -> d9• d7 + d9 -> d10• d1 XOR d9 -> d11• d3 XOR d9 -> d12• d2 XOR d10 -> d13• d4 XOR d10 -> d14

Después de estos pasos los bloques d11, d13, d12, d14 (con ese orden) son usados comoentradas en la siguiente vuelta de encriptado, con las próximas seis claves s7 a s12. Esteprocedimiento se realiza ocho veces (ocho vueltas) hasta obtener los cuatro bloques de salida quellamamos e1, e2, e3, e4. El proceso de encriptado se completa con las siguientes operaciones:

• e1 * s49 -> c1• e2 + s50 -> c2• e3 + s51 -> c3• e4 * s52 -> c4

Los bloques finales c1, c2, c3, c4 forman el bloque de salida encriptado de 64 bits. Elproceso completo se repite para sucesivos bloques de 64 bits de texto claro hasta que el texto originalcompleto es encriptado.

Para desencriptar se usa el mismo proceso pero con un conjunto de subclaves distintas.Las subclaves de desencriptado (relativas a las subclaves de encriptado s1 a s52) son mostradas en lasiguiente tabla:

1ra vuelta s49* s50# s51# s52* s47 s48 2da vuelta s43* s45# s44# s46* s41 s42 3ra vuelta s37* s39# s38# s39* s35 s36 4ta vuelta s31* s33# s32# s34* s29 s30 5ta vuelta s25* s27# s26# s28* s23 s24 6ta vuelta s19* s21# s20# s22* s17 s18 7ma vuelta s13* s15# s14# s16* s11 s12 8va vuelta s7* s9# s8# s10* s5 s6Transformación final s1* s2# s3# s4*

sXX* es el inverso multiplicativo de sXX módulo ((2^16) +1)sXX# es el inverso aditivo de sXX módulo (2^16).

EL ALGORITMO MD5

El algoritmo MD5 de message digests está publicado en la Request For Comment1321, ya que se pretende que pase a ser standard. La RFC incluye una implementación en C.

El algoritmo MD5 recibe como entrada un mensaje de longitud arbitraria,obteniéndose a la salida lo que se conoce como "fingerprint" o "message digest" de la entraday cuya longitud es de 128 bits.

Esta función de hash cumple con las propiedades de las funciones de hash suguras:1. Es computacionalmente infactible encontrar dos mensajes cualesquiera que

tengan el mismo message digest.2. Dado un message digest es computacionalmente infactible encontrar un

mensaje cualquiera que lo produzca.Se comienza suponiendo que se tiene un mensaje de b bits de longitud, escritos m0,

m1, ...,m(b-1). El algoritmo tiene cinco pasos:

Paso 1: Adición de bits de relleno.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página12

El mensaje es rellenado con bits, de tal manera que le falte a su longitud 64 bitspara ser un múltiplo de 512. De esos bits que se agregan, el primero es 1 y el resto son 0.

Paso 2: Adición de la longitud.

Una representación de 64 bits de b (la longitud del mensaje antes de agregar losbits de relleno) es agregada al resultado del paso anterior en forma de dos palabras de 32 bits,yendo en primer lugar la que contiene los bits menos significativos. Si la longitud del mensajefuera mayor que 2^64, solamente se usan los 64 bits menos significativos de b.

De esta manera, la longitud del mensaje es ahora múltiplo de 512. Este mensajetambién tiene una longitud que es múltiplo de 16 words de 32bits. Decimos entonces que M[0... N-1] representa las words del mensaje resultante, donde N es un múltiplo de 16.

Paso 3: Inicialización de los bufferes.

Se usa un buffer de cuatro words (A, B, C, D), para obtener el digest del mensaje.Cada word son registros de 32 bits y son inicializados a los siguientes valores:

A: 01 23 45 67B: 89 ab cd efC: fe dc ba 98D: 76 54 32 10

Paso 4: Procesado del mensaje en bloques de 16 words.

En primer lugar se definen cuatro funciones auxiliares que tienen como entradatres words de 32 bits y como salida una word de 32 bits.

F(X,Y,Z) = (X AND Y) OR ((NOT(X)) AND Z)G(X,Y,Z) = (X AND Z) OR (Y AND (NOT(Z))H(X,Y,Z) = X XOR Y XOR ZI(X,Y,Z) = Y XOR (X OR (NOT(Z)))

En este paso se utiliza una tabla de 64 elementos T[1 ... 64] construídos a partir dela función seno. Donde T[i] indica el elemento en la posición i de la tabla que es igual a laparte entera de 4294967296 veces abs(sin(i)), y donde i está en radianes. X[i] es el bloque dedatos y <<s indica rotación de s bits.

El proceso es el siguiente:

/*Procesar cada bloque de 16 words. */For i = 0 to N/16-1 do

/*Copiar bloque i en X. */For j = 0 to 15 doSet X[j] to M[i*16+j].end /* of loop on j */

/* Grabar A como AA, B como BB, C como CC, y D como DD. */AA = ABB = BCC = CDD = D

/* Primera etapa. *//* [abcd k s i] denota la operación a = b + ((a + F(b,c,d) + X[k] + T[i]) << s) *//* Realizar estas 16 operaciones. */

Criptografía y Seguridad

Informática

Pretty Good Privacy Página13

[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4][ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8][ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12][ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]

/*Segunda etapa. *//* [abcd k s i] denota la operación a = b + ((a + G(b,c,d) + X[k] + T[i]) << s) *//* Realizar estas 16 operaciones. */[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20][ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24][ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28][ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]

/*Tercera etapa. *//* [abcd k s t] denota la operación a = b + ((a + H(b,c,d) + X[k] + T[i]) << s) *//* Realizar estas 16 operaciones. */[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36][ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40][ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44][ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]

/*Cuarta etapa. *//* [abcd k s t] denota la operación a = b + ((a + I(b,c,d) + X[k] + T[i]) << s) *//* Realizar estas 16 operaciones. */[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52][ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56][ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60][ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]

/* Incrementar los registros*/A = A + AAB = B + BBC = C + CCD = D + DD

end /* del bucle i */

Paso 5: Salida.

El message digest producido es A, B, C, D, empezando con los bits menossignificativos de A y terminando con los más significativos de D. Independientemente de lalongitud del mensaje será de 128 bits.

Se ha calculado que con este algoritmo la dificultad, medida en operaciones, deconseguir dos mensajes con el mismo digest está en 2^64.

El SHA (SECURE HASH STANDARD)

1. INTRODUCCION

El SHA-1 (Secure Hash Algorithm) es utilizado junto con el DSA (Digital Signature Algorithm) como seespecifica en el DSS (Digital Signature Standard) y cuando un algoritmo de hash es requerido paraaplicaciones federales. Para un mensaje de longitud < 2^64 bits, el SHA-1 produce una representacióncondensada del mensaje de 160 bits, llamada mensaje diggest(mensaje comprimido). El mensaje diggestes usado durante el proceso de generación de la firma del mensaje, y también para el proceso de

Criptografía y Seguridad

Informática

Pretty Good Privacy Página14

verificación de la firma del mensaje. Cualquier cambio del mensaje durante la transmisión del mismo,resultara con muy alta probabilidad un diferente mensaje diggest, y la verificación de la firma fallará

El SHA-1 esta diseñado para tener las siguientes propiedades, es computacionalmente impracticableencontrar un mensaje que corresponda a un dado mensaje diggest, o encontrar dos mensajes queproduzcan el mismo mensaje diggest.

2. CADENAS DE BITS Y ENTEROS

Será usada la siguiente terminología para referirse a cadenas de bits y enteros.

a) Un digito hexaadecimal(hexa) es un elemento de el conjunto {0, 1, ... , 9, A, ... , F}. Un dígito hexaesta representado por una cadena de 4 bits. Ejemplo: 7 = 0111, A = 1010.

b) Una palabra(word) de 32 bits esta representado por una secuencia de 8 dígitos hexa. Para convertiruna palabra de 8 dígitos hexa, se toma cadenas de a 4 bits y se convierte a su equivalente hexa comose describió anteriormente. Ejemplo: 1010 0001 0000 0011 1111 1110 0010 0011 = A103FE23.

c) Un entero entre 0 y 2^32 - 1 inclusive, puede ser representado como una palabra. Los 4 bits menossignificantes de un entero son representados por el dígito hexa que se encuentra mas a la derecha dela palabra. Ejemplo: el entero 291 = 2^8+2^5+2^1+2^0 = 256+32+2+1 esta representado por lapalabra hexa 00000123.

Si z es un entero, 0<=z<2^64, entonces z= 2^32(x + y), donde 0<=x<2^32 y 0<=y<2^32. Como x ey pueden estar representado como palabras X e Y, entonces z puede estar representado por el par depala- bras (X,Y).d) Bloque = cadena de 512 bits = secuencia de 16 palabras.

3. OPERACIONES SOBRE PALABRAS

Los siguientes operadores lógicos serán aplicados a palabras:.

a) Operaciones lógicas aplicadas a palabras

X AND Y = "and " entre X e Y.

X OR Y = "or inclusivo" entre X e Y.

X XOR Y = "or exclusivo" entre X e Y.

NOT X = complemento de X.

Ejemplo:

01101100101110011101001001111011

XOR

01100101110000010110100110110111

------------------------------------------------

= 00001001011110001011101111001100

b) Para enteros positivos n y m, la operación n mod m, devuelve el resto de la división n div m.

c) La operación circular de cambio izquierdo S^n(X), donde X es una palabra y n es un enterocomprendido entre 0<= n<32, esta definida como:

Criptografía y Seguridad

Informática

Pretty Good Privacy Página15

S^n(X) = (X << n) OR (X >> 32-n)

Donde X << n se obtiene descartando los n bits que están mas a la izquierda de X y luego llenar conn ceros a la derecha(el resultado será de 32 bits) y X >> n se obtiene descartando los n bits que estánmas a la derecha de X y luego se llena con n ceros a la izquierda. Por lo tanto S^n(X) es equivalente a uncam- bio circular de X por n posiciones a la izquierda.

4. LLENADO DEL MENSAJE

El SHA-1 es utilizado para obtener un mensaje comprimido, a partir de un mensaje o archivo de datos quees provisto como entrada. El mensaje o archivo de datos deberá ser considerada como una cadena de bits.La longitud de el mensaje es el numero de bits en el mensaje( el mensaje vacío tiene longitud 0). Si elnumero de bits en un mensaje es un múltiplo de 8, para compactarlo se puede representar en hexa. Elpropósito del llenado del mensaje es hacer que la longitud total del mensaje llenado sea un múltiplo de512. El SHA-1 produce secuencialmente bloques de 512 bits, cuando hace el computo para obtener elmensaje comprimido. Para lograr un mensaje llenado de longitud 512*n, a partir del mensaje original, enel final del mensaje se agrega un "1" seguido por n "0", seguido por un entero de 64 bits L, que indica lalongitud del mensaje original. Luego el mensaje llenado es procesado por el SHA-1 como n bloques de512 bits.

Suponiendo un mensaje de longitud L<2^64. Antes de entrar al SHA-1, el mensaje es completado de lasiguiente manera:

a. "1" es insertado. Ejemplo: si el mensaje original es "01010000", este quedaría como "010100001".b. "0" son insertados. El numero de ceros dependerá de la longitud del mensaje original. Los últimos 64

bits son reservados para indicar la longitud L del mensaje original.

Ejemplo: Suponiendo que el mensaje original es la cadena de bits

01100001 01100010 01100011 01100100 01100101

Luego del paso (a) este queda

01100001 01100010 01100011 01100100 01100101 1.

Como L=40, el numero de bits de la cadena anterior es 41, por lo tanto se le debe agregar 407 "0",haciendo un total de 448 bits. Esto queda en hexa como:

61626364 65800000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000.

El mensaje llenado estará compuesto de 16*n palabras para algún n>0. El mensaje llenado es tomadocomo una secuencia de n bloques M(1), M(2), M(3), ...., M(n), donde cada M(i) contiene 16 palabras yM(1) contiene los primeros caracteres ( o bits) de el mensaje.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página16

5. FUNCIONES USADAS

Una secuencia de funciones lógicas f(0), f(1),...,f(79) son usadas en el SHA-1.Cada f(t), 0 <= t <= 79, opera sobre tres palabras de 32-bit B, C, D y cuya salida es una palabra de 32 bits,f(t;B,C,D) está definida de la siguiente forma:

f(t;B,C,D) = (B AND C) OR ((NOT B) AND D) ( 0 <= t <= 19)

f(t;B,C,D) = B XOR C XOR D (20 <= t <= 39)

f(t;B,C,D) = (B AND C) OR (B AND D) OR (C AND D) (40 <= t <= 59)

f(t;B,C,D) = B XOR C XOR D (60 <= t <= 79).

6. CONSTANTES USADAS

Una secuencia de palabras constantes K(0), K(1), ... , K(79) son usadas en el SHA-1.

Cuyos valores en hexa son los siguientes:

K(t) = 5A827999 ( 0 <= t <= 19)

K(t) = 6ED9EBA1 (20 <= t <= 39)

K(t) = 8F1BBCDC (40 <= t <= 59)

K(t) = CA62C1D6 (60 <= t <= 79).

7. REALIZANDO EL COMPRIMIDO DE EL MENSAJE

El mensaje comprimido es computado usando el mensaje llenado. Para el computo se usan, 2 buffersdonde cada uno consiste de 5 palabras de 32 bits y una secuencia de 80 palabras de 32 bits. Las palabrasdel primer buffer son etiquetadas como A, B, C, D, E. Las palabras de segundo buffers son tambiénetiquetadas como H0, H1, H2, H3, H4. Las palabras correspondientes a la secuencia de 80 palabras sonetiquetadas como W(0), W(1), W(2),......, W(79). También es empleado un buffer del tamaño de 1 palabrallamado TEMP.Para generar el mensaje diggest, los 16 bloques M(1), M(2),....,M(n) definidos en la sección 4 sonprocesados en orden. El proceso de cada M(i) envuelve 80 pasos.

Antes de procesar cualquier bloque, los H's son inicializados como se muestra:

en hexa,

H0 = 67452301

H1 = EFCDAB89

H2 = 98BADCFE

H3 = 10325476

H4 = C3D2E1F0.

Ahora los M(1), M(2), ... , M(n) son procesados. Para procesar los M(i), se procede de la siguiente forma:

a. Se divide M(i) en 16 words W(0), W(1), ... , W(15), donde W(0) es la palabra que esta mas a la izquierda. b. for t = 16 to 79 let

Criptografía y Seguridad

Informática

Pretty Good Privacy Página17

W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16)). c. Let A = H0, B = H1, C = H2, D = H3, E = H4. d. For t = 0 to 79 do

TEMP = S^5(A) + f(t;B,C,D) + E + W(t) + K(t);

E = D; D = C; C = S^30(B); B = A; A = TEMP;

e. Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E.

Luego de procesar M(n), el mensaje es la cadena de 160 bits representada por las 5 palabras

H0 H1 H2 H3 H4.

8. METODO ALTERNATIVO PARA EL COMPUTO DEL MENSAJE DIGGEST

En la sección anterior se asumió que la secuencia W(0),.....,W(79) esta implementada como un array de80 palabras de 32 bits. Esto es eficiente desde el punto de vista de optimizar el tiempo de ejecución, perosi se quiere optimizar espacio, una alternativa es tomar W(t) como una cola circular, que se implementausando un array de 16 palabras de 32 bits W[0], ... W[15]. En este caso, se utiliza un constante MASK =0000000F.

El procesamiento de M(i) es el siguiente:

a. Se divide M(i) en 16 palabras W[0], ... , W[15], donde W[0] es la palabra que se encuentra mas a la izquierda. b. Let A = H0, B = H1, C = H2, D = H3, E = H4. c. For t = 0 to 79 do

s = t AND MASK; if (t >= 16) W[s] = S^1(W[(s + 13) AND MASK] XOR W[(s + 8) AND MASK]

XOR W[(s + 2) AND MASK] XOR W[s]);

TEMP = S^5(A) + f(t;B,C,D) + E + W[s] + K(t);

E = D; D = C; C = S^30(B); B = A; A = TEMP; d. Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E.

9. COMPARACION DE METODOS

Los métodos de la sección 7 y 8 llegan al mismo mensaje diggest. El método de la sección 8 es mas lentodebido a la complejidad en el calculo de { W[t] }.

APENDICE A . EJEMPLO DE COMPRESION DE UN MENSAJE.

Se toma como mensaje original el código binario ASCII de "abc"

01100001 01100010 01100011.

Este mensaje tiene longitud L = 24. En el paso (a) de la sección 4, agregamos "1". En paso (b)agregamos 423 "0"s. En el paso (c) agregamos el hexa 00000000 00000018, que son las 2 palabras querepresentan la longitud 24. Por lo tanto el mensaje llenado consiste de un bloque( n = 1).

Los valores iniciales en hexa de {Hi} son

Criptografía y Seguridad

Informática

Pretty Good Privacy Página18

H0 = 67452301H1 = EFCDAB89H2 = 98BADCFEH3 = 10325476H4 = C3D2E1F0.

Comienzo del proceso del bloque 1. Las palabras del bloque 1 son:

W[0] = 61626380 W[1] = 00000000 W[2] = 00000000 W[3] = 00000000 W[4] = 00000000 W[5] = 00000000 W[6] = 00000000 W[7] = 00000000 W[8] = 00000000 W[9] = 00000000 W[10] = 00000000 W[11] = 00000000 W[12] = 00000000 W[13] = 00000000 W[14] = 00000000 W[15] = 00000018.

Los valores hexa def A,B,C,D,E después de pasar por el loop "for t = 0 to 79" son:

A B C D E

t = 0: 0116FC33 67452301 7BF36AE2 98BADCFE 10325476

t = 1: 8990536D 0116FC33 59D148C0 7BF36AE2 98BADCFE

t = 2: A1390F08 8990536D C045BF0C 59D148C0 7BF36AE2

t = 3: CDD8E11B A1390F08 626414DB C045BF0C 59D148C0

t = 4: CFD499DE CDD8E11B 284E43C2 626414DB C045BF0C

t = 5: 3FC7CA40 CFD499DE F3763846 284E43C2 626414DB

t = 6: 993E30C1 3FC7CA40 B3F52677 F3763846 284E43C2

t = 7: 9E8C07D4 993E30C1 0FF1F290 B3F52677 F3763846

t = 8: 4B6AE328 9E8C07D4 664F8C30 0FF1F290 B3F52677

t = 9: 8351F929 4B6AE328 27A301F5 664F8C30 0FF1F290

t = 10: FBDA9E89 8351F929 12DAB8CA 27A301F5 664F8C30

t = 11: 63188FE4 FBDA9E89 60D47E4A 12DAB8CA 27A301F5

t = 12: 4607B664 63188FE4 7EF6A7A2 60D47E4A 12DAB8CA

t = 13: 9128F695 4607B664 18C623F9 7EF6A7A2 60D47E4A

t = 14: 196BEE77 9128F695 1181ED99 18C623F9 7EF6A7A2

Criptografía y Seguridad

Informática

Pretty Good Privacy Página19

t = 15: 20BDD62F 196BEE77 644A3DA5 1181ED99 18C623F9

t = 16: 4E925823 20BDD62F C65AFB9D 644A3DA5 1181ED99

t = 17: 82AA6728 4E925823 C82F758B C65AFB9D 644A3DA5

t = 18: DC64901D 82AA6728 D3A49608 C82F758B C65AFB9D

t = 19: FD9E1D7D DC64901D 20AA99CA D3A49608 C82F758B

t = 20: 1A37B0CA FD9E1D7D 77192407 20AA99CA D3A49608

t = 21: 33A23BFC 1A37B0CA 7F67875F 77192407 20AA99CA

t = 22: 21283486 33A23BFC 868DEC32 7F67875F 77192407

t = 23: D541F12D 21283486 0CE88EFF 868DEC32 7F67875F

t = 24: C7567DC6 D541F12D 884A0D21 0CE88EFF 868DEC32

t = 25: 48413BA4 C7567DC6 75507C4B 884A0D21 0CE88EFF

t = 26: BE35FBD5 48413BA4 B1D59F71 75507C4B 884A0D21

t = 27: 4AA84D97 BE35FBD5 12104EE9 B1D59F71 75507C4B

t = 28: 8370B52E 4AA84D97 6F8D7EF5 12104EE9 B1D59F71

t = 29: C5FBAF5D 8370B52E D2AA1365 6F8D7EF5 12104EE9

t = 30: 1267B407 C5FBAF5D A0DC2D4B D2AA1365 6F8D7EF5

t = 31: 3B845D33 1267B407 717EEBD7 A0DC2D4B D2AA1365

t = 32: 046FAA0A 3B845D33 C499ED01 717EEBD7 A0DC2D4B

t = 33: 2C0EBC11 046FAA0A CEE1174C C499ED01 717EEBD7

t = 34: 21796AD4 2C0EBC11 811BEA82 CEE1174C C499ED01

t = 35: DCBBB0CB 21796AD4 4B03AF04 811BEA82 CEE1174C

t = 36: 0F511FD8 DCBBB0CB 085E5AB5 4B03AF04 811BEA82

t = 37: DC63973F 0F511FD8 F72EEC32 085E5AB5 4B03AF04

t = 38: 4C986405 DC63973F 03D447F6 F72EEC32 085E5AB5

t = 39: 32DE1CBA 4C986405 F718E5CF 03D447F6 F72EEC32

t = 40: FC87DEDF 32DE1CBA 53261901 F718E5CF 03D447F6

t = 41: 970A0D5C FC87DEDF 8CB7872E 53261901 F718E5CF

t = 42: 7F193DC5 970A0D5C FF21F7B7 8CB7872E 53261901

t = 43: EE1B1AAF 7F193DC5 25C28357 FF21F7B7 8CB7872E

Criptografía y Seguridad

Informática

Pretty Good Privacy Página20

t = 44: 40F28E09 EE1B1AAF 5FC64F71 25C28357 FF21F7B7

t = 45: 1C51E1F2 40F28E09 FB86C6AB 5FC64F71 25C28357

t = 46: A01B846C 1C51E1F2 503CA382 FB86C6AB 5FC64F71

t = 47: BEAD02CA A01B846C 8714787C 503CA382 FB86C6AB

t = 48: BAF39337 BEAD02CA 2806E11B 8714787C 503CA382

t = 49: 120731C5 BAF39337 AFAB40B2 2806E11B 8714787C

t = 50: 641DB2CE 120731C5 EEBCE4CD AFAB40B2 2806E11B

t = 51: 3847AD66 641DB2CE 4481CC71 EEBCE4CD AFAB40B2

t = 52: E490436D 3847AD66 99076CB3 4481CC71 EEBCE4CD

t = 53: 27E9F1D8 E490436D 8E11EB59 99076CB3 4481CC71

t = 54: 7B71F76D 27E9F1D8 792410DB 8E11EB59 99076CB3

t = 55: 5E6456AF 7B71F76D 09FA7C76 792410DB 8E11EB59

t = 56: C846093F 5E6456AF 5EDC7DDB 09FA7C76 792410DB

t = 57: D262FF50 C846093F D79915AB 5EDC7DDB 09FA7C76

t = 58: 09D785FD D262FF50 F211824F D79915AB 5EDC7DDB

t = 59: 3F52DE5A 09D785FD 3498BFD4 F211824F D79915AB

t = 60: D756C147 3F52DE5A 4275E17F 3498BFD4 F211824F

t = 61: 548C9CB2 D756C147 8FD4B796 4275E17F 3498BFD4

t = 62: B66C020B 548C9CB2 F5D5B051 8FD4B796 4275E17F

t = 63: 6B61C9E1 B66C020B 9523272C F5D5B051 8FD4B796

t = 64: 19DFA7AC 6B61C9E1 ED9B0082 9523272C F5D5B051

t = 65: 101655F9 19DFA7AC 5AD87278 ED9B0082 9523272C

t = 66: 0C3DF2B4 101655F9 0677E9EB 5AD87278 ED9B0082

t = 67: 78DD4D2B 0C3DF2B4 4405957E 0677E9EB 5AD87278

t = 68: 497093C0 78DD4D2B 030F7CAD 4405957E 0677E9EB

t = 69: 3F2588C2 497093C0 DE37534A 030F7CAD 4405957E

t = 70: C199F8C7 3F2588C2 125C24F0 DE37534A 030F7CAD

t = 71: 39859DE7 C199F8C7 8FC96230 125C24F0 DE37534A

t = 72: EDB42DE4 39859DE7 F0667E31 8FC96230 125C24F0

Criptografía y Seguridad

Informática

Pretty Good Privacy Página21

t = 73: 11793F6F EDB42DE4 CE616779 F0667E31 8FC96230

t = 74: 5EE76897 11793F6F 3B6D0B79 CE616779 F0667E31

t = 75: 63F7DAB7 5EE76897 C45E4FDB 3B6D0B79 CE616779

t = 76: A079B7D9 63F7DAB7 D7B9DA25 C45E4FDB 3B6D0B79

t = 77: 860D21CC A079B7D9 D8FDF6AD D7B9DA25 C45E4FDB

t = 78: 5738D5E1 860D21CC 681E6DF6 D8FDF6AD D7B9DA25

t = 79: 42541B35 5738D5E1 21834873 681E6DF6 D8FDF6AD.

El Bloque 1 ha sido procesado. Los valores de {Hi} son

H0 = 67452301 + 42541B35 = A9993E36 H1 = EFCDAB89 + 5738D5E1 = 4706816A H2 =98BADCFE + 21834873 = BA3E2571 H3 = 10325476 + 681E6DF6 = 7850C26C H4 =C3D2E1F0 + D8FDF6AD = 9CD0D89D.

Mensaje comprimido = A9993E36 4706816A BA3E25717850C26C 9CD0D89D

APENDICE B. SEGUNDO EJEMPLO DE COMPRESION DE UN MENSAJE

Se toma como mensaje original el codigo binario ASCII de"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".

Cada uno de los 56 caracteres son convertidos a 8 bits, por lo tanto la longitud del mensaje es L = 448bits.En el paso (a) de la sección 4, agregamos "1". En paso (b) agregamos 511 "0"s. En el paso (c)agregamos el hexa 00000000 000001C0 que son las 2 palabras que representan la longitud 448. Por lotanto el mensaje llenado consiste de dos bloque( n = 2).

Los valores iniciales de {Hi} son:

H0 = 67452301H1 = EFCDAB89H2 = 98BADCFEH3 = 10325476H4 = C3D2E1F0.

Comienzo del proceso del bloque 1. Las palabras del bloque 1 son:

W[0] = 61626364 W[1] = 62636465 W[2] = 63646566 W[3] = 64656667 W[4] = 65666768 W[5] = 66676869 W[6] = 6768696A W[7] = 68696A6B W[8] = 696A6B6C W[9] = 6A6B6C6D W[10] = 6B6C6D6E W[11] = 6C6D6E6F W[12] = 6D6E6F70 W[13] = 6E6F7071

Criptografía y Seguridad

Informática

Pretty Good Privacy Página22

W[14] = 80000000 W[15] = 00000000.

Los valores hexa def A,B,C,D,E despues de pasar por el loop "for t = 0 to 79" son:

A B C D E

t = 0: 0116FC17 67452301 7BF36AE2 98BADCFE 10325476

t = 1: EBF3B452 0116FC17 59D148C0 7BF36AE2 98BADCFE

t = 2: 5109913A EBF3B452 C045BF05 59D148C0 7BF36AE2

t = 3: 2C4F6EAC 5109913A BAFCED14 C045BF05 59D148C0

t = 4: 33F4AE5B 2C4F6EAC 9442644E BAFCED14 C045BF05

t = 5: 96B85189 33F4AE5B 0B13DBAB 9442644E BAFCED14

t = 6: DB04CB58 96B85189 CCFD2B96 0B13DBAB 9442644E

t = 7: 45833F0F DB04CB58 65AE1462 CCFD2B96 0B13DBAB

t = 8: C565C35E 45833F0F 36C132D6 65AE1462 CCFD2B96

t = 9: 6350AFDA C565C35E D160CFC3 36C132D6 65AE1462

t = 10: 8993EA77 6350AFDA B15970D7 D160CFC3 36C132D6

t = 11: E19ECAA2 8993EA77 98D42BF6 B15970D7 D160CFC3

t = 12: 8603481E E19ECAA2 E264FA9D 98D42BF6 B15970D7

t = 13: 32F94A85 8603481E B867B2A8 E264FA9D 98D42BF6

t = 14: B2E7A8BE 32F94A85 A180D207 B867B2A8 E264FA9D

t = 15: 42637E39 B2E7A8BE 4CBE52A1 A180D207 B867B2A8

t = 16: 6B068048 42637E39 ACB9EA2F 4CBE52A1 A180D207

t = 17: 426B9C35 6B068048 5098DF8E ACB9EA2F 4CBE52A1

t = 18: 944B1BD1 426B9C35 1AC1A012 5098DF8E ACB9EA2F

t = 19: 6C445652 944B1BD1 509AE70D 1AC1A012 5098DF8E

t = 20: 95836DA5 6C445652 6512C6F4 509AE70D 1AC1A012

t = 21: 09511177 95836DA5 9B111594 6512C6F4 509AE70D

t = 22: E2B92DC4 09511177 6560DB69 9B111594 6512C6F4

t = 23: FD224575 E2B92DC4 C254445D 6560DB69 9B111594

t = 24: EEB82D9A FD224575 38AE4B71 C254445D 6560DB69

t = 25: 5A142C1A EEB82D9A 7F48915D 38AE4B71 C254445D

Criptografía y Seguridad

Informática

Pretty Good Privacy Página23

t = 26: 2972F7C7 5A142C1A BBAE0B66 7F48915D 38AE4B71

t = 27: D526A644 2972F7C7 96850B06 BBAE0B66 7F48915D

t = 28: E1122421 D526A644 CA5CBDF1 96850B06 BBAE0B66

t = 29: 05B457B2 E1122421 3549A991 CA5CBDF1 96850B06

t = 30: A9C84BEC 05B457B2 78448908 3549A991 CA5CBDF1

t = 31: 52E31F60 A9C84BEC 816D15EC 78448908 3549A991

t = 32: 5AF3242C 52E31F60 2A7212FB 816D15EC 78448908

t = 33: 31C756A9 5AF3242C 14B8C7D8 2A7212FB 816D15EC

t = 34: E9AC987C 31C756A9 16BCC90B 14B8C7D8 2A7212FB

t = 35: AB7C32EE E9AC987C 4C71D5AA 16BCC90B 14B8C7D8

t = 36: 5933FC99 AB7C32EE 3A6B261F 4C71D5AA 16BCC90B

t = 37: 43F87AE9 5933FC99 AADF0CBB 3A6B261F 4C71D5AA

t = 38: 24957F22 43F87AE9 564CFF26 AADF0CBB 3A6B261F

t = 39: ADEB7478 24957F22 50FE1EBA 564CFF26 AADF0CBB

t = 40: D70E5010 ADEB7478 89255FC8 50FE1EBA 564CFF26

t = 41: 79BCFB08 D70E5010 2B7ADD1E 89255FC8 50FE1EBA

t = 42: F9BCB8DE 79BCFB08 35C39404 2B7ADD1E 89255FC8

t = 43: 633E9561 F9BCB8DE 1E6F3EC2 35C39404 2B7ADD1E

t = 44: 98C1EA64 633E9561 BE6F2E37 1E6F3EC2 35C39404

t = 45: C6EA241E 98C1EA64 58CFA558 BE6F2E37 1E6F3EC2

t = 46: A2AD4F02 C6EA241E 26307A99 58CFA558 BE6F2E37

t = 47: C8A69090 A2AD4F02 B1BA8907 26307A99 58CFA558

t = 48: 88341600 C8A69090 A8AB53C0 B1BA8907 26307A99

t = 49: 7E846F58 88341600 3229A424 A8AB53C0 B1BA8907

t = 50: 86E358BA 7E846F58 220D0580 3229A424 A8AB53C0

t = 51: 8D2E76C8 86E358BA 1FA11BD6 220D0580 3229A424

t = 52: CE892E10 8D2E76C8 A1B8D62E 1FA11BD6 220D0580

t = 53: EDEA95B1 CE892E10 234B9DB2 A1B8D62E 1FA11BD6

t = 54: 36D1230A EDEA95B1 33A24B84 234B9DB2 A1B8D62E

Criptografía y Seguridad

Informática

Pretty Good Privacy Página24

t = 55: 776C3910 36D1230A 7B7AA56C 33A24B84 234B9DB2

t = 56: A681B723 776C3910 8DB448C2 7B7AA56C 33A24B84

t = 57: AC0A794F A681B723 1DDB0E44 8DB448C2 7B7AA56C

t = 58: F03D3782 AC0A794F E9A06DC8 1DDB0E44 8DB448C2

t = 59: 9EF775C3 F03D3782 EB029E53 E9A06DC8 1DDB0E44

t = 60: 36254B13 9EF775C3 BC0F4DE0 EB029E53 E9A06DC8

t = 61: 4080D4DC 36254B13 E7BDDD70 BC0F4DE0 EB029E53

t = 62: 2BFAF7A8 4080D4DC CD8952C4 E7BDDD70 BC0F4DE0

t = 63: 513F9CA0 2BFAF7A8 10203537 CD8952C4 E7BDDD70

t = 64: E5895C81 513F9CA0 0AFEBDEA 10203537 CD8952C4

t = 65: 1037D2D5 E5895C81 144FE728 0AFEBDEA 10203537

t = 66: 14A82DA9 1037D2D5 79625720 144FE728 0AFEBDEA

t = 67: 6D17C9FD 14A82DA9 440DF4B5 79625720 144FE728

t = 68: 2C7B07BD 6D17C9FD 452A0B6A 440DF4B5 79625720

t = 69: FDF6EFFF 2C7B07BD 5B45F27F 452A0B6A 440DF4B5

t = 70: 112B96E3 FDF6EFFF 4B1EC1EF 5B45F27F 452A0B6A

t = 71: 84065712 112B96E3 FF7DBBFF 4B1EC1EF 5B45F27F

t = 72: AB89FB71 84065712 C44AE5B8 FF7DBBFF 4B1EC1EF

t = 73: C5210E35 AB89FB71 A10195C4 C44AE5B8 FF7DBBFF

t = 74: 352D9F4B C5210E35 6AE27EDC A10195C4 C44AE5B8

t = 75: 1A0E0E0A 352D9F4B 7148438D 6AE27EDC A10195C4

t = 76: D0D47349 1A0E0E0A CD4B67D2 7148438D 6AE27EDC

t = 77: AD38620D D0D47349 86838382 CD4B67D2 7148438D

t = 78: D3AD7C25 AD38620D 74351CD2 86838382 CD4B67D2

t = 79: 8CE34517 D3AD7C25 6B4E1883 74351CD2 86838382.

El Bloque 1 ha sido procesado. Los valores de H(i) son los siguientes:

H0 = 67452301 + 8CE34517 = F4286818H1 = EFCDAB89 + D3AD7C25 = C37B27AE H2 =98BADCFE + 6B4E1883 = 0408F581 H3 = 10325476 + 74351CD2 = 84677148 H4 =C3D2E1F0 + 86838382 = 4A566572.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página25

Comienzo del proceso del bloque 2. Las palabras del bloque 2 son:

W[0] = 00000000 W[1] = 00000000 W[2] = 00000000 W[3] = 00000000 W[4] = 00000000 W[5] = 00000000 W[6] = 00000000 W[7] = 00000000 W[8] = 00000000 W[9] = 00000000 W[10] = 00000000 W[11] = 00000000 W[12] = 00000000 W[13] = 00000000 W[14] = 00000000 W[15] = 000001C0.

Los valores hexa def A,B,C,D,E después de pasar por el loop "for t = 0 to 79" son:

A B C D E

t = 0: 2DF257E9 F4286818 B0DEC9EB 0408F581 84677148

t = 1: 4D3DC58F 2DF257E9 3D0A1A06 B0DEC9EB 0408F581

t = 2: C352BB05 4D3DC58F 4B7C95FA 3D0A1A06 B0DEC9EB

t = 3: EEF743C6 C352BB05 D34F7163 4B7C95FA 3D0A1A06

t = 4: 41E34277 EEF743C6 70D4AEC1 D34F7163 4B7C95FA

t = 5: 5443915C 41E34277 BBBDD0F1 70D4AEC1 D34F7163

t = 6: E7FA0377 5443915C D078D09D BBBDD0F1 70D4AEC1

t = 7: C6946813 E7FA0377 1510E457 D078D09D BBBDD0F1

t = 8: FDDE1DE1 C6946813 F9FE80DD 1510E457 D078D09D

t = 9: B8538ACA FDDE1DE1 F1A51A04 F9FE80DD 1510E457

t = 10: 6BA94F63 B8538ACA 7F778778 F1A51A04 F9FE80DD

t = 11: 43A2792F 6BA94F63 AE14E2B2 7F778778 F1A51A04

t = 12: FECD7BBF 43A2792F DAEA53D8 AE14E2B2 7F778778

t = 13: A2604CA8 FECD7BBF D0E89E4B DAEA53D8 AE14E2B2

t = 14: 258B0BAA A2604CA8 FFB35EEF D0E89E4B DAEA53D8

t = 15: D9772360 258B0BAA 2898132A FFB35EEF D0E89E4B

t = 16: 5507DB6E D9772360 8962C2EA 2898132A FFB35EEF

Criptografía y Seguridad

Informática

Pretty Good Privacy Página26

t = 17: A51B58BC 5507DB6E 365DC8D8 8962C2EA 2898132A

t = 18: C2EB709F A51B58BC 9541F6DB 365DC8D8 8962C2EA

t = 19: D8992153 C2EB709F 2946D62F 9541F6DB 365DC8D8

t = 20: 37482F5F D8992153 F0BADC27 2946D62F 9541F6DB

t = 21: EE8700BD 37482F5F F6264854 F0BADC27 2946D62F

t = 22: 9AD594B9 EE8700BD CDD20BD7 F6264854 F0BADC27

t = 23: 8FBAA5B9 9AD594B9 7BA1C02F CDD20BD7 F6264854

t = 24: 88FB5867 8FBAA5B9 66B5652E 7BA1C02F CDD20BD7

t = 25: EEC50521 88FB5867 63EEA96E 66B5652E 7BA1C02F

t = 26: 50BCE434 EEC50521 E23ED619 63EEA96E 66B5652E

t = 27: 5C416DAF 50BCE434 7BB14148 E23ED619 63EEA96E

t = 28: 2429BE5F 5C416DAF 142F390D 7BB14148 E23ED619

t = 29: 0A2FB108 2429BE5F D7105B6B 142F390D 7BB14148

t = 30: 17986223 0A2FB108 C90A6F97 D7105B6B 142F390D

t = 31: 8A4AF384 17986223 028BEC42 C90A6F97 D7105B6B

t = 32: 6B629993 8A4AF384 C5E61888 028BEC42 C90A6F97

t = 33: F15F04F3 6B629993 2292BCE1 C5E61888 028BEC42

t = 34: 295CC25B F15F04F3 DAD8A664 2292BCE1 C5E61888

t = 35: 696DA404 295CC25B FC57C13C DAD8A664 2292BCE1

t = 36: CEF5AE12 696DA404 CA573096 FC57C13C DAD8A664

t = 37: 87D5B80C CEF5AE12 1A5B6901 CA573096 FC57C13C

t = 38: 84E2A5F2 87D5B80C B3BD6B84 1A5B6901 CA573096

t = 39: 03BB6310 84E2A5F2 21F56E03 B3BD6B84 1A5B6901

t = 40: C2D8F75F 03BB6310 A138A97C 21F56E03 B3BD6B84

t = 41: BFB25768 C2D8F75F 00EED8C4 A138A97C 21F56E03

t = 42: 28589152 BFB25768 F0B63DD7 00EED8C4 A138A97C

t = 43: EC1D3D61 28589152 2FEC95DA F0B63DD7 00EED8C4

t = 44: 3CAED7AF EC1D3D61 8A162454 2FEC95DA F0B63DD7

t = 45: C3D033EA 3CAED7AF 7B074F58 8A162454 2FEC95DA

Criptografía y Seguridad

Informática

Pretty Good Privacy Página27

t = 46: 7316056A C3D033EA CF2BB5EB 7B074F58 8A162454

t = 47: 46F93B68 7316056A B0F40CFA CF2BB5EB 7B074F58

t = 48: DC8E7F26 46F93B68 9CC5815A B0F40CFA CF2BB5EB

t = 49: 850D411C DC8E7F26 11BE4EDA 9CC5815A B0F40CFA

t = 50: 7E4672C0 850D411C B7239FC9 11BE4EDA 9CC5815A

t = 51: 89FBD41D 7E4672C0 21435047 B7239FC9 11BE4EDA

t = 52: 1797E228 89FBD41D 1F919CB0 21435047 B7239FC9

t = 53: 431D65BC 1797E228 627EF507 1F919CB0 21435047

t = 54: 2BDBB8CB 431D65BC 05E5F88A 627EF507 1F919CB0

t = 55: 6DA72E7F 2BDBB8CB 10C7596F 05E5F88A 627EF507

t = 56: A8495A9B 6DA72E7F CAF6EE32 10C7596F 05E5F88A

t = 57: E785655A A8495A9B DB69CB9F CAF6EE32 10C7596F

t = 58: 5B086C42 E785655A EA1256A6 DB69CB9F CAF6EE32

t = 59: A65818F7 5B086C42 B9E15956 EA1256A6 DB69CB9F

t = 60: 7AAB101B A65818F7 96C21B10 B9E15956 EA1256A6

t = 61: 93614C9C 7AAB101B E996063D 96C21B10 B9E15956

t = 62: F66D9BF4 93614C9C DEAAC406 E996063D 96C21B10

t = 63: D504902B F66D9BF4 24D85327 DEAAC406 E996063D

t = 64: 60A9DA62 D504902B 3D9B66FD 24D85327 DEAAC406

t = 65: 8B687819 60A9DA62 F541240A 3D9B66FD 24D85327

t = 66: 083E90C3 8B687819 982A7698 F541240A 3D9B66FD

t = 67: F6226BBF 083E90C3 62DA1E06 982A7698 F541240A

t = 68: 76C0563B F6226BBF C20FA430 62DA1E06 982A7698

t = 69: 989DD165 76C0563B FD889AEF C20FA430 62DA1E06

t = 70: 8B2C7573 989DD165 DDB0158E FD889AEF C20FA430

t = 71: AE1B8E7B 8B2C7573 66277459 DDB0158E FD889AEF

t = 72: CA1840DE AE1B8E7B E2CB1D5C 66277459 DDB0158E

t = 73: 16F3BABB CA1840DE EB86E39E E2CB1D5C 66277459

t = 74: D28D83AD 16F3BABB B2861037 EB86E39E E2CB1D5C

Criptografía y Seguridad

Informática

Pretty Good Privacy Página28

t = 75: 6BC02DFE D28D83AD C5BCEEAE B2861037 EB86E39E

t = 76: D3A6E275 6BC02DFE 74A360EB C5BCEEAE B2861037

t = 77: DA955482 D3A6E275 9AF00B7F 74A360EB C5BCEEAE

t = 78: 58C0AAC0 DA955482 74E9B89D 9AF00B7F 74A360EB

t = 79: 906FD62C 58C0AAC0 B6A55520 74E9B89D 9AF00B7F.

El Bloque 2 ha sido procesado. Los valores de H(i) son:

H0 = F4286818 + 906FD62C = 84983E44H1 = C37B27AE + 58C0AAC0 = 1C3BD26EH2 =0408F581 + B6A55520 = BAAE4AA1H3 = 84677148 + 74E9B89D = F95129E5H4 =4A566572 + 9AF00B7F = E54670F1. Mensaje comprimido = 84983E44 1C3BD26E BAAE4AA1F95129E5 E54670F1

APENDICE C.TERCER EJEMPLO DE COMPRESION DE MENSAJE

Se toma como mensaje original el código binario ASCII de una cadena que consiste de 1,000,000 deletras "a".

Mensaje comprimido = 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F

Ataques a PGP.

1- El cifrado asimétrico.

Para entender el ataque sobre RSA, es importante comprender como trabaja este.Brevemente:

1- Se hallan dos grandes números primos p y q.2- Se halla n=p.q (el modulo público).3- Se elige e, donde e<n y es primo relativo de (p-1).(q-1)4- Se calcula d=e^-1 en modulo (p-1).(q-1)5- e es el exponente público y d el exponente privado.6- La clave pública es (n,e) y la privada es (n,d)7- p y q nunca deben ser dadas a conocer, preferiblemente deberían ser destruidas.

La encriptación se realiza dividiendo el mensaje en bloques menores que n y aplicando luegoexponenciación modular: c=m^e mod nLa desencriptación es la operación inversa: m=c^d mod n

Factorización del RSA por fuerza bruta.

El atacante tiene acceso a la clave pública, o sea, a e y n. Su objetivo es hallar d, paraobtenerla es necesario factorizar a n (esto es así debido a que resulta mas fácil factorizar n quetratar de deducir o hallar (p-1) (q-1)). Este tipo de ataque es uno de los mejores que se hanutilizado hasta la fecha. Algunos de los algoritmos utilizados son los siguientes:

Criptografía y Seguridad

Informática

Pretty Good Privacy Página29

1- Trial division: el más antiguo y menos eficiente. Examina todo los númerosprimos menores o iguales a la raíz cuadrada de n.

2- Quadratic Sieve (QS): el algoritmo mas rápido para números menores que110 dígitos.

3- Multiple Polynomial Quadratic Sieve(MPQS): Mas rápido que QS.4- Double Large Prime Variation of the MPQS: aun mas rápido.5- Number Field Sieve (NFS): actualmente el algoritmo mas rápido conocido

para números de mas de 110 dígitos.Aun así, factorizar grandes números es difícil. Aunque se esta volviendo mas fácil con elcorrer de los años debido a los avances de la teoría de números y la potencia de computo de lasnuevas máquinas. En 1977 Ron Rivest dijo que factorizar un número de 125 dígitos podríatomar 40 cuatrillones de años. En 1994 el RSA129 fue factorizado en el termino de 500 MIPS-años. En 1995 la clave Backnet (116 dígitos) fue factorizada en 400 MIPS-años (1 MIPS-añoes igual a 1millon de instrucciones por segundo para una computadora corriendo por un año).La siguiente tabla muestra el esfuerzo estimado para factorizar algunas claves públicas RSAusando Number Field Sieve:

Tamaño de clave MIPS-años requerido para factorizar ------------------------------------------------------------------------ 512 30,000 768 200,000,000 1024 300,000,000,000 2048 300,000,000,000,000,000,000

La siguiente tabla muestra una equivalencia estimada para forzar claves simétricas yasimétricas por medio de NFS:

Simétrico Asimétrico ------------------------------------------------ 56-bits 384-bits 64-bits 512-bits 80-bits 768-bits 112-bits 1792-bits

128-bits 2304-bits

Números primos.

RSA obtiene su seguridad a partir de que presume que la factorización de grandesnúmeros primos es difícil. Por lo tanto, PGP necesita una forma de generar grandes númerosprimos; por el momento no existe un camino factible para generarlos. Por otro lado existe unacantidad infinita de números primos. El teorema de números primos da una convenienteaproximación para la función de distribución de números primos PI(n); que especifica elnúmero de primos menores o iguales que n:

limite n ------> infinito PI(n) / [ n / (ln (n) )] == 1

Por lo tanto, la aproximación n/ln(n) es razonable para determinar la densidad de númerosprimos menores o iguales a n, por ejemplo:

Criptografía y Seguridad

Informática

Pretty Good Privacy Página30

Hay 17 números primos entre 1-60

60 / ln(60) = 14.65

hay un error de 8 % aproximadamente.

Dado el número n un camino para determinar si es primo es por medio de divisionessucesivas, o sea, tratar de dividir n por cada entero 2,3,..,sqr(n). Si n es primo, ninguno de losdivisores usados podrá dividirlo. Este método no es practico debido al tiempo necesario paraverificar la condición de número primo, especialmente cuando el número es de varios dígitos.

Pseudo-primos

Existe un test que permite verificar si un número es un candidato para ser númeroprimo. Este consta de cuatro pasos:

Test de Fermat

1- Se ingresa el número n.2- Se toman los cuatro primeros números primos b={2,3,5,7}.3- Se toma b^(n-1)%n = w.4- Si w == 1 para todo b, n es probablemente primo. En otro caso n no es primo.

Resulta prácticamente imposible que un número dado como primo sea compuesto. Cada vezque se aplica el test la posibilidad de que no sea primo es en la primera pasada de 1 en 10^13,en la segunda es de 1 en 10^26 y en la tercera es de 1 en 10^52. El test de Fermat no descartaun número primo.

Los números Carmichael

Desdichadamente existen números que no son primos que satisfacen la ecuaciónb^(n-1)%n. Estos números son bastante raros y solo existen 255 sobre 10^9 números. Losprimeros números Carmichael son : 561, 1105 y 1729. La posibilidad de PGP de generar unode estos númeroses de 1 en 10^50.

Ataques a RSA esotéricos.

Estos ataques no presentan un problema para RSA en si, si no para ciertasimplementaciones del protocolo. La mayoría son omitidos en PGP.

Ataque a los textos cifrados elegidos.

El atacante escucha sobre un canal inseguro en que los mensajes RSA sontransmitidos. El atacante toma un mensaje encriptado c que es destinado a otra persona. Elatacante busca leer el mensaje sin tomar un serio esfuerzo en factorisar. En otras palabrasbusca m=c^d.

Para recobrar m, el atacante primero elige un número aleatorio r < n, luego el atacantecalcula:

1- x = r^e mod n;2- y=xc mod n3- t=r^-1 mod n

El atacante cuenta con el hecho de que:

si x = r^e mod n, entonces r = x^d mod n

Criptografía y Seguridad

Informática

Pretty Good Privacy Página31

El atacante le envía y al destino firmado con su propia clave y luego el atacante recibe u = y^dmod n , para por último este computar:

tu mod n = (r^-1)(y^d) mod n = (r^-1)(x^d)(c^d) mod n = (c^d) mod n = m

Exponente e muy chico.

Sí e es un número muy chico no incide sobre la seguridad de RSA. Si se encripta conuna clave pública pequeña las operaciones se tornan mas rápidas (algunos valores comunesson: 3, 17 y 65537). El problema de usar valores pequeños se da cuando se encripta mensajespequeños. Si tenemos como e a 3 y tenemos además un mensaje m tan chico como la raízcúbica de n, entonces el mensaje puede ser recobrado tomando la raíz cúbica de m debido aque:

m [ para m <= 3 rdroot(n)]^3 mod n será equivalente a m^3

y por consiguiente:

3 rdroot(m^3) = m

Para defenderse de este ataque, simplemente se rellena el mensaje antes de laencriptación, dado que m^3 será siempre reducido a mod n.

PGP utiliza un valor e pequeño para el exponente de encriptación, por defecto estetrata de utilizar 17. Si no puede computar d con e igual a 17, PGP itera e hasta 19, y tratanuevamente. PGP utiliza seguramente como relleno un valor aleatorio mayor a n.

Ataque por medición de tiempo contra RSA.

Es una nueva área de ataque público descubierto por Paul Kocher que trato con elhecho de que los diferentes operaciones criptográficas toman diferentes cantidades discretaspara el proceso. Si los cálculos del RSA son hechos sin tener en cuenta el teorema del ChineseRemeider, lo siguiente se aplica:

Un atacante puede aprovechar estas diferencias de tiempo en los computos del RSA,en muchos casos recobrando a d. El ataque es pasivo ya que este se sitúa sobre la red y observalas operaciones RSA. El atacante observa pasivamente k operaciones y el tiempo t que tomacada operación de exponenciación modular: m = c^d mod n. El atacante conocerá c y n. Elseudo-código del ataque sería el siguiente:

Algoritmo para calcular m=c^d mod n:

Let m0 = 1. Let c0 = x. For i=0 upto (bits in d-1): If (bit i of d) is 1 then Let mi+1 = (mi * ci) mod n. Else Let mi+1 = mi. Let di+1 = di^2 mod n. End.

Esta modalidad de ataque es relativamente nueva y no se han hecho grandesseguimientos sobre su efectividad.

Rivest habla de introducir un valor aleatorio en el proceso de desencriptación. Dadoque:

m = c^d mod n

Criptografía y Seguridad

Informática

Pretty Good Privacy Página32

se torna:

m = r^-1 (c r^e)^d mod n

donde r es un número aleatorio y r^-1 su inversa.PGP no es vulnerable a este tipo de ataque se si se aumenta la velocidad del RSA. Y

dado que las operaciones encriptado e desencriptado se realizan en off-line, esto resulta masimpractico ya que el atacante necesita observar las operaciones criptográficas en tiempo real.

2- El cifrado simétrico.

Ataque por fuerza bruta sobre IDEA.

Como ya sabemos el espacio claves de IDEA es de 128 bits. Para recobrar una claveparticular uno debe buscar el la mitad del espacio de claves, o sea en 127 bits.

Si se contara con 1.000.000.000 de máquinas que puedan procesar 1.000.000.000claves por segundo les tomaría un tiempo tan grande como la existencia del universo parahallar la clave. IDEA, respecto de la tecnología actual, no es vulnerable al ataque por fuerzabruta.

Manual de referencia PGP 5.0

Creación de un nuevo par de claves

1. Haga clic sobre el botón de inicio de Windows y elija PGPkeys desde el submenú PGP del menúProgramas, o desde PGPtray. También puede abrir esta ventana haciendo clic sobre el icono de lasllaves dobles ubicado en la barra de herramientas de su aplicación de correo electrónico.Se abre la ventana PGPkeys.

2. Elija Nueva desde el Menú Claves. El Asistente de Generación de Claves PGP proporciona algunainformación introductoria en la primer pantalla.

3. Una vez leída esta información haga clic en Siguiente para avanzar a la pantalla siguiente.El Asistente de Generación de Claves PGP le pide que escriba su nombre de usuario y dirección decorreo electrónico.

4. Escriba su nombre en la primera línea y su dirección de correo electrónico en la segunda línea.No es absolutamente necesario escribir su nombre real o aún su dirección de correo electrónico. Sinembargo, usando su nombre real facilita que otros lo identifiquen como el dueño de su clave pública.También, usando su dirección de correo electrónico correcta, usted y los demás pueden aprovecharuna característica del complemento PGP [plug-in], que automáticamente busca en su archivo de clavesla clave apropiada, cuando dirige el correo a un destinatario en particular.

5. Haga clic en Siguiente para avanzar a la pantalla siguiente.El Asistente de Generación de Claves le pide que especifique un tamaño para sus nuevas claves.

6. Elija un tamaño de clave entre 768 y 3072 bits, o escriba un tamaño personalizado entre 512 y 4096bits.

7. Haga clic en Siguiente para avanzar a la pantalla siguiente.

8. Indique cuándo desea que caduquen sus claves. Puede aceptar la opción predeterminada que esNunca, o poner un número específico de días después del cual las claves caducarán.

9. Haga clic en Siguiente para avanzar a la pantalla siguiente.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página33

10. En el cuadro de diálogo Contraseña PGP, escriba la secuencia de caracteres o palabras que desee usarpara mantener acceso exclusivo a su clave privada. Para confirmar lo que ha escrito, avance a lasiguiente línea con la tecla de Tabulación, y repita la contraseña.

11. Haga clic en Siguiente para empezar el proceso de generación de claves.

12. Haga clic en Siguiente para avanzar a la pantalla siguiente.

13. Si corresponde, firme su nueva clave con la más vieja y escriba la frase de contraseña de la clave másvieja, y luego haga clic en Siguiente.

14. Especifique si desea que su nueva clave pública sea enviada al servidor de claves, y luego haga clicen Siguiente.

15. Haga clic en Terminar.

Envío de su clave pública a un servidor de claves

1. Abra la ventana PGPkeys haciendo clic sobre el icono de la llave y el candado en la Barra de Tareasdel sistema.

2. Seleccione el icono que representa la clave pública que desea publicar en el servidor.

3. Desde el menú Claves elija Enviar a Servidor. Como alternativa, puede apretar el botón derecho delratón y elegir Enviar a Servidor de Claves desde el menú emergente.

4. Desde el submenú Enviar a Servidor, elija el servidor de claves al cual desea enviar sus claves.Dependiendo de su entorno PGP, puede tener varios para elegir.

Incluir su clave pública en un mensaje de correo electrónico

1. Abra la ventana PGPkeys haciendo clic sobre el icono del candado y la llave en la Barra de Tareas delsistema.

2. Seleccione su par de claves y luego elija Copiar desde el menú Edición.

3. Abra el editor que usted usa para componer sus mensajes de correo electrónico, ubique el cursor en elárea deseada, y luego desde el menú Edición elija Pegar. En las aplicaciones de correo electrónico másnuevas, sólo tiene que arrastrar su clave desde la ventana PGPkeys al texto de su mensaje de correoelectrónico para transferir la información de la clave.

Obtención de la clave pública de alguien de un servidor de clavespúblicas

1. Abra la ventana PGPkeys haciendo clic sobre el icono del candado y la llave en la Barra de Tareas delsistema.

2. Desde la ventana PGPkeys, menú Ver, elija Buscar Clave.Aparece la pantalla Buscar.

3. Use el menú para introducir el criterio de búsqueda para localizar los usuarios de claves públicas.

Soportadas Cifrar y firmar con aplicaciones de correo electrónico.

1. Use su aplicación de correo electrónico para componer su mensaje de correo electrónico del modo quelo haría normalmente.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página34

2. Cuando usted haya terminado de componer el texto de su mensaje de correo electrónico, especifique sidesea cifrar y firmar el texto de su mensaje haciendo clic sobre los botones del candado y la pluma deave.

3. Envíe su mensaje de correo electrónico como lo hace normalmente.Si ha elegido firmar los datos cifrados, aparece el cuadro de diálogo Contraseña pidiéndole sucontraseña antes que el mensaje sea enviado.

4. Escriba su contraseña y luego haga clic en Aceptar.

5. Arrastre las claves públicas de quienes van a recibir una copia del mensaje de correo electrónicocifrado dentro del cuadro que lista los “Destinatarios”. También puede hacer doble clic sobrecualquiera de las claves para moverlas desde un área de la pantalla al otro.

6. Haga clic en Aceptar para enviar su mensaje.

Descifrar y verificar desde aplicaciones de correo electrónicosoportadas.

1. Abra su mensaje de correo electrónico como lo hace normalmente. Verá un bloque de texto cifrado, ininteligible, en el cuerpo de su mensaje de correo electrónico.

2. Para descifrar y verificar el contenido del mensaje de correo electrónico, haga clicsobre el botón del sobre abierto en la barra de herramientas de su aplicación.Aparece el cuadro de diálogo Contraseña PGP, pidiéndole que escriba su contraseña.

3. Escriba su contraseña y luego haga clic en Aceptar.El mensaje es entonces descifrado. Si ha sido firmado, aparece un panel que indica si la firma esválida.

4. Después que usted haya leído el mensaje, puede guardarlo en su estado descifrado, o puede guardar laversión original cifrada para que permanezca segura.

Creación de un grupo

1. Elija Nuevo Grupo desde el menú Grupos

2. Escriba el nombre del Grupo.

3. Si lo desea, puede escribir una descripción del grupo, la cual aparece como Propiedades de Grupo.

Adición de miembros a un grupo

1. Seleccione la clave de la persona a ser incluida en un grupo, desde la ventana PGPkeys.

2. Arrastre el nombre de usuario desde la ventana PGPkeys al grupo deseado en el cuadro Grupos.

Eliminación de un grupo

1. Seleccione el grupo desde el cuadro Grupos de la ventana PGPkeys.

2. Presione la tecla Supr o elija Eliminar Grupos desde el menú emergente.

Agregación de un grupo a otro grupo

1. Seleccione el grupo que usted desea ubicar dentro de otro grupo.

2. Arrastre el grupo seleccionado dentro del otro grupo.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página35

Eliminación de miembros de un grupo

1. Seleccione el miembro del grupo a ser eliminado.

2. Elija Eliminar desde el menú emergente.PGP le pide que confirme la acción.

3. Confirme la acción presionando Sí.Envío de mensajes cifrados de correo electrónico a grupos

1. Dirija el mensaje a su grupo de correoEl nombre del grupo al que va a cifrar debe corresponderse con el nombre del grupo de correoelectrónico. Su administrador de correo electrónico puede haber configurado grupos de correoelectrónico, como ingeniería o finanzas.

2. Cifre el mensaje.

3. Envíe el mensaje.

Cifrar y firmar por medio del portapapeles

1. Use el editor suministrado con su aplicación de correo electrónico o su procesador de textos favoritopara crear el archivo.

2. Cuando está listo para enviar el mensaje, seleccione el área de texto que desea cifrar, o elijaSeleccionar Todo desde el menú Edición.

3. Elija Copiar desde el menú Edición para copiar el contenido de su mensaje al portapapeles.

4. Haga clic sobre el icono del candado y la llave en la barra de tareas del sistema y elija CifrarPortapapeles, Firmar Portapapeles, o Cifrar y Firmar Portapapeles.

5. Arrastre las claves públicas de quienes van a recibir una copia del mensaje de correo electrónico en elcuadro que lista los Destinatarios.

6. Haga clic en Aceptar.

7. Escriba su contraseña, y luego haga clic en Aceptar.

8. Si usted está enviando el archivo cifrado en un mensaje de correo electrónico, copie el mensajecifrado en su aplicación de correo electrónico.

9. Envíe su correo electrónico o guarde el archivo cifrado en su disco duro o servidor de archivos.

Para descifrar y verificar por medio del portapapeles

1. En el editor suministrado con su aplicación, seleccione el texto cifrado y luego cópielo alportapapeles.En la mayoría de las aplicaciones, elija Copiar desde el menú Edición para copiar el texto alportapapeles de Windows.

2. Haga clic sobre el icono del candado y la llave en la barra de tareas del sistema para abrir el menúemergente PGP. Elija Descifrar/Verificar Portapapeles para iniciar el proceso de descifrado yverificación.Aparece el cuadro de diálogo Contraseña PGP pidiéndole que escriba su contraseña.

3. Escriba su contraseña y haga clic en Aceptar.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página36

El mensaje es descifrado. Si ha sido firmado, aparece un mensaje indicando si la firma es válida.

4. Para ver el contenido descifrado del mensaje de correo electrónico, elija Editar Portapapeles desde elmenú emergente PGP. Usted puede entonces copiar el contenido del portapapeles de vuelta en sueditor de texto y guardarlo si lo desea.

Para cifrar y firmar desde el Explorador de Windows

1. Abra el Explorador de Windows desde el menú Inicio.

2. Seleccione el archivo (o archivos) que desea cifrar.

3. Elija la opción deseada desde el submenú PGP del menú Archivo o desde el menú emergente al cualaccede presionando el botón derecho del ratón.

4. Seleccione las claves públicas arrastrándolas a la lista Destinatarios y luego haga clic en Aceptar.

5. Especifique la ubicación y escriba el nombre del archivo donde usted desea guardar la versión cifradadel mismo. La extensión .pgp es automáticamente agregada al nombre del archivo, a menos que ustedhaya activado la opción Armadura ASCII, en cuyo caso es usada la extensión .asc.

6. Haga clic en Guardar para guardar el archivo en la ubicación especificada.

Descifrar y verificar desde el Explorador de Windows

1. Abra el Explorador de Windows desde el menú de inicio.

2. Seleccione el archivo (o archivos) que desea descifrar y verificar.

3. Elija Descifrar/Verificar desde el submenú PGP del menú Archivo, o presione el botón derecho delratón para abrir el menú emergente PGP y luego elija Descifrar/Verificar. Aparece el cuadro dediálogo Contraseña PGP pidiéndole que escriba su contraseña.

4. Escriba su contraseña y luego haga clic en Aceptar.Si el archivo ha sido firmado, aparece un mensaje que indica si la firma es válida.

5. Haga clic en Aceptar.

6. Especifique la ubicación y escriba el nombre del archivo donde desea guardar la versión descifradadel mismo.

7. Haga clic sobre el botón Guardar para guardar el archivo.

Tachado de archivos

1. Abra el Explorador de Windows desde el menú Inicio.

2. Seleccione el archivo o los archivos que desea tachar.

3. Abra el menú emergente PGP o acceda a PGPtools.

4. Elija Tachar.

5. Seleccione el archivo o elija Abrir desde el cuadro de diálogo Seleccionar Archivos para tachar el archivo.

6. Haga clic en Aceptar para tachar el o los archivos.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página37

Par de claves predeterminado, especificación

1. Seleccione el par de claves que quiere designar como predeterminado.

2. Elija Establecer como Clave Predeterminada desde el menú Claves.La selección es mostrada en negrita, lo que indica que ahora es su par de claves predeterminado.

Nuevo nombre o dirección de usuario, procedimiento para añadir auna clave existente

1. Seleccione el par de claves para el que quiera añadir otro nombre o dirección de usuario.

2. Elija Añadir Nombre desde el menú Claves

3. Escriba el nuevo nombre y luego presione el tabulador para ir al siguiente campo.

4. Escriba la nueva dirección de correo electrónico y luego haga clic sobre Aceptar.

5. Escriba su contraseña y luego haga clic sobre Aceptar.

Huella de una clave, Procedimiento de Comprobación

1. Seleccione la clave cuya huella quiera comprobar.

2. Elija Propiedades de Clave desde el menú Claves.

3. Anote la huella y compárela con la original.

Firma de una clave pública, Procedimiento

1. Seleccione la clave que desea firmar.

2. Elija Firmar desde el menú Claves.

3. Se le pregunta si permite que la firma pueda ser exportada. Otros pueden confiar en su firma.

4. Si quisiera enviar la clave con su firma a un servidor de claves, marque la casilla Enviar Firma aServidor de Claves. La clave pública en el servidor es actualizada para reflejar la inclusión de sufirma. La mayoría de los usuarios prefieren usar su propio criterio cuando permiten a otros que firmensus claves, de modo que siempre es una buena idea hablar con el propietario de la clave antes deañadir su firma a la copia en el servidor.

5. Haga clic en Aceptar para indicar su certeza que la clave realmente pertenece al supuesto dueño.

6. Aparece el cuadro de diálogo Contraseña de Firma PGP. Se le pide que escriba la contraseña para supar de claves predeterminado.

7. Cuando firme la clave pública de otra persona, es mostrado para esa clave un icono asociado a sunombre de usuario.

Nivel de confianza para validaciones de clave, procedimiento deasignación1. Seleccione la clave cuyo nivel de confianza desea cambiar. Elija Propiedades de Clave desde el menú

Claves. Aparece el cuadro de diálogo Propiedades

Criptografía y Seguridad

Informática

Pretty Good Privacy Página38

2. Use la barra deslizante para establecer el nivel de confianza apropiado para la clave: Sin Confianza,Marginal o Completa.

3. Haga clic sobre Aceptar para activar la nueva configuración.

Inhabilitación de una clave, procedimiento

1. Seleccione la clave que quiera inhabilitar

2. Elija Inhabilitar desde el menú Claves

Habilitación de una clave, procedimiento

1. Elija la clave que quiera habilitar

2. Elija Habilitar desde el menú Claves.

Eliminación de una clave, firma, o ID de usuario, procedimiento

1. Seleccione la clave, firma o ID de usuario que quiera eliminar.

2. Elija Borrar desde el menú Edición.

Cambio de contraseña, procedimiento

1. Seleccione el par de claves cuya contraseña quiere cambiar.

2. Elija Propiedades de Clave desde el menú Claves.

3. Haga clic sobre Cambiar Contraseña.

4. Escriba la contraseña a ser cambiada en el campo superior y avance al campo siguiente con eltabulador.

5. Escriba su nueva contraseña en el campo central y avance al campo siguiente con el tabulador.

6. Confirme su nueva contraseña escribiéndola de nuevo.

7. Haga clic en Aceptar.

Importación de una clave desde un archivo, procedimiento

1. Elija Importar desde el menú Claves.

2. Seleccione el archivo que contiene la clave que quiere importar y haga clic en Abrir.

Exportación de una clave a un archivo

1. Seleccione la clave que desea exportar a un archivo.

2. Elija Exportar desde el menú Claves.

3. Escriba el nombre del archivo al cual desea exportar la clave y luego haga clic sobre Guardar.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página39

Adición de una clave desde un mensaje de correo electrónico

1. Con el mensaje de correo electrónico abierto, abra la ventana PGPkeys.

2. Ajuste las dos ventanas de modo que pueda ver parte de la ventana PGPkeys detrás de la ventana delmensaje.

3. Seleccione el texto de la clave, comprendido entre BEGIN PGP PUBLIC KEY BLOCK [COMIENZODEL BLOQUE DE CLAVE PÚBLICA PGP] y END PGP PUBLIC KEY BLOCK [FIN DELBLOQUE DE CLAVE PÚBLICA PGP] inclusive.

4. Aparece el cuadro de diálogo ‘Seleccionar Claves para Importar’, mostrando las claves incluidas enel mensaje. Elija las claves que desea copiar eligiendo Seleccionar Todo, Anular Selección, Importaro Cancelar.

5. Las claves nuevas aparecerán en la ventana PGPkeys.

Revocación de una clave, procedimiento

1. Seleccione el par de claves que va a revocar.

2. Elija Revocar desde el menú Claves.

3. Haga clic sobre Sí para confirmar su intención de revocar la clave seleccionada.

4. Escriba su contraseña y haga clic sobre Aceptar.

5. Envíe la clave revocada al servidor de claves para que todos sepan que no deben usar su clave antigua.

Búsqueda de la clave de un usuario, procedimiento

1. Abra la ventana PGPkeys

2. Elija Buscar desde el menú Claves

3. En el menú Buscar Claves, elija la ubicación desde la cual usted desea buscar claves

4. Especifique su objeto de búsqueda

5. Especifique las condiciones que está buscando.

6. Escriba los criterios de búsqueda.

7. Haga clic en Buscar para comenzar la búsqueda.

8. Haga clic en Limpiar Búsqueda para vaciar la ventana de búsqueda y limpiar los criterios debúsqueda.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página40

Código fuente de los principales algoritmos del PGP.

RSA

/* rsagen.c - C source code for RSA public-key key generationroutines.

First version 17 Mar 87

(c) Copyright 1987 by Philip Zimmermann. All rights reserved. The author assumes no liability for damages resulting from theuse of this software, even if the damage results from defects inthis software. No warranty is expressed or implied.

RSA-specific routines follow. These are the only functions thatare specific to the RSA public key cryptosystem. The othermultiprecision integer math functions may be used for non-RSAapplications. Without these functions that follow, the rest ofthe software cannot perform the RSA public key algorithm.

The RSA public key cryptosystem is patented by the MassachusettsInstitute of Technology (U.S. patent #4,405,829). This patent

doesnot apply outside the USA. Public Key Partners (PKP) holds theexclusive commercial license to sell and sub-license the RSA

publickey cryptosystem. The author of this software implementation of

theRSA algorithm is providing this software for educational use

only.Licensing this algorithm from PKP is the responsibility of you,

theuser, not Philip Zimmermann, the author of this software. The

authorassumes no liability for any breach of patent law resulting from

theunlicensed use of this software by the user.

*/

#include "mpilib.h"#include "genprime.h"#include "rsagen.h"#include "random.h"#include "rsaglue.h"

#ifdef MACTC5extern DialogPtr ProgressDialog;#endif

Criptografía y Seguridad

Informática

Pretty Good Privacy Página41

static void derive_rsakeys(unitptr n,unitptr e,unitptr d,unitptr p,unitptr q,unitptr u,short ebits);/* Given primes p and q, derive RSA key components n, e, d, and

u. */

/* Define some error status returns for RSA keygen... */#define KEYFAILED -15 /* key failed final test */

#define swap(p,q) { unitptr t; t = p; p = q; q = t; }

static void derive_rsakeys(unitptr n, unitptr e, unitptr d,unitptr p, unitptr q, unitptr u, short ebits)

/* * Given primes p and q, derive RSA key components n, e, d, and u. * The global_precision must have already been set large enough for n. * Note that p must be < q. * Primes p and q must have been previously generated elsewhere. * The bit precision of e will be >= ebits. The search for a usable * exponent e will begin with an ebits-sized number. The recommended * value for ebits is 5, for efficiency's sake. This could yield * an e as small as 17. */{

unit F[MAX_UNIT_PRECISION];unitptr ptemp, qtemp, phi, G; /* scratchpads */

/* For strong prime generation only, latitude is the amountwhich the modulus may differ from the desired bit

precision.It must be big enough to allow primes to be generated bygoodprime reasonably fast.

*/#define latitude(bits) (max(min(bits/16,12),4))/* between 4 and 12bits */

ptemp = d; /* use d for temporary scratchpad array */qtemp = u; /* use u for temporary scratchpad array */phi = n; /* use n for temporary scratchpad array */G = F; /* use F for both G and F */

if (mp_compare(p,q) >= 0) /* ensure that p<q for computing u*/

swap(p,q); /* swap the pointers p and q */

/* phi(n) is the Euler totient function of n, or the number ofpositive integers less than n that are relatively prime to

n.G is the number of "spare key sets" for a given modulus n.The smaller G is, the better. The smallest G can get is 2.

*/mp_move(ptemp,p); mp_move(qtemp,q);mp_dec(ptemp); mp_dec(qtemp);mp_mult(phi,ptemp,qtemp); /* phi(n) = (p-1)*(q-1) */mp_gcd(G,ptemp,qtemp); /* G(n) = gcd(p-1,q-1) */

#ifdef DEBUGif (countbits(G) > 12) /* G shouldn't get really big. */

Criptografía y Seguridad

Informática

Pretty Good Privacy Página42

mp_display("\007G = ",G); /* Worry the user. */#endif /* DEBUG */

mp_udiv(ptemp,qtemp,phi,G); /* F(n) = phi(n)/G(n) */mp_move(F,qtemp);

/* * We now have phi and F. Next, compute e... * Strictly speaking, we might get slightly faster results by * testing all small prime e's greater than 2 until we hit a * good e. But we can do just about as well by testing all * odd e's greater than 2. * We could begin searching for a candidate e anywhere, perhaps * using a random 16-bit starting point value for e, or even * larger values. But the most efficient value for e would be

3, * if it satisfied the gcd test with phi. * Parameter ebits specifies the number of significant bits e * should have to begin search for a workable e. * Make e at least 2 bits long, and no longer than one bit * shorter than the length of phi. */ebits = min(ebits,countbits(phi)-1);if (ebits==0) ebits=5; /* default is 5 bits long */ebits = max(ebits,2);mp_init(e,0);mp_setbit(e,ebits-1);lsunit(e) |= 1; /* set e candidate's lsb - make it odd */mp_dec(e); mp_dec(e); /* precompensate for preincrements of e

*/do {

mp_inc(e); mp_inc(e); /* try odd e's until we get it. */mp_gcd(ptemp,e,phi); /* look for e such that

gcd(e,phi(n)) = 1 */} while (testne(ptemp,1));

/* Now we have e. Next, compute d, then u, then n.d is the multiplicative inverse of e, mod F(n).u is the multiplicative inverse of p, mod q, if p<q.n is the public modulus p*q.

*/mp_inv(d,e,F); /* compute d such that (e*d) mod F(n) = 1

*/mp_inv(u,p,q); /* (p*u) mod q = 1, assuming p<q */mp_mult(n,p,q); /* n = p*q */mp_burn(F); /* burn the evidence on the stack */

} /* derive_rsakeys */

int rsa_keygen(unitptr n, unitptr e, unitptr d,unitptr p, unitptr q, unitptr u, short keybits, short ebits)

/* * Generate RSA key components p, q, n, e, d, and u. * This routine sets the global_precision appropriate for n, * where keybits is desired precision of modulus n. * The precision of exponent e will be >= ebits. * It will generate a p that is < q. * Returns 0 for succcessful keygen, negative status otherwise. */{

Criptografía y Seguridad

Informática

Pretty Good Privacy Página43

short pbits, qbits;boolean too_close_together; /* TRUE iff p and q are too close */int status;int slop;

/* * Don't let keybits get any smaller than 2 units, because * some parts of the math package require at least 2 units * for global_precision. * Nor any smaller than the 32 bits of preblocking overhead. * Nor any bigger than MAX_BIT_PRECISION - SLOP_BITS. * Also, if generating "strong" primes, don't let keybits get * any smaller than 64 bits, because of the search latitude. */slop = max(SLOP_BITS,1); /* allow at least 1 slop bit for sign

bit */keybits = min(keybits,(MAX_BIT_PRECISION-slop));keybits = max(keybits,UNITSIZE*2);keybits = max(keybits,32); /* minimum preblocking overhead */

#ifdef STRONGPRIMESkeybits = max(keybits,64); /* for strong prime search latitude

*/#endif /* STRONGPRIMES */

set_precision(bits2units(keybits + slop));

/* We will need a series of truly random bits to generate theprimes. We need enough random bits for keybits, plus tworandom units for combined discarded bit losses in

randombits.Since we now know how many random bits we will need,this is the place to prefill the pool of random bits.

*/trueRandAccum(keybits+2*UNITSIZE);

#if 0/* * If you want primes of different lengths ("separation" bits

apart), * do the following: */pbits = (keybits-separation)/2;qbits = keybits - pbits;

#elsepbits = keybits/2;qbits = keybits - pbits;

#endif

trueRandConsume(pbits); /* "use up" this many bits */

#ifdef MACTC5ShowWindow(ProgressDialog);DrawDialog(ProgressDialog);

#endif

#ifdef STRONGPRIMES /* make a good strong prime for the key */status = goodprime(p,pbits,pbits-latitude(pbits));

#else /* just any random prime will suffice for the key */status = randomprime(p,pbits);

Criptografía y Seguridad

Informática

Pretty Good Privacy Página44

#endif /* else not STRONGPRIMES */if (status < 0)

return(status); /* failed to find a suitable prime */

/* We now have prime p. Now generate q such that q>p... */

qbits = keybits - countbits(p);

trueRandConsume(qbits); /* "use up" this many bits *//* This load of random bits will be stirred and recycled until

a good q is generated. */

do { /* Generate a q until we get one that isn't too close to p.*/#ifdef STRONGPRIMES /* make a good strong prime for the key */

status = goodprime(q,qbits,qbits-latitude(qbits));#else /* just any random prime will suffice for the key */

status = randomprime(q,qbits);#endif /* else not STRONGPRIMES */

if (status < 0)return(status); /* failed to find a suitable prime

*/

/* Note that at this point we can't be sure that q>p. */if (mp_compare(p,q) >= 0) { /* ensure that p<q

for computing u */mp_move(u,p);mp_move(p,q);mp_move(q,u);

}/* See if p and q are far enough apart. Is q-p big enough?

*/mp_move(u,q); /* use u as scratchpad */mp_sub(u,p); /* compute q-p */too_close_together = (countbits(u) < (countbits(q)-7));

/* Keep trying q's until we get one far enough from p... */} while (too_close_together);

derive_rsakeys(n,e,d,p,q,u,ebits);trueRandFlush(); /* ensure recycled random pool is destroyed */

/* Now test key just to make sure --this had better work! */{

unit C[MAX_UNIT_PRECISION];int i;

/* Create a dummy signature */for (i = 0; i < 16; i++)

((byte *)C)[i] = 3*i+7;/* Encrypt it */

status = rsa_private_encrypt(C,(byte *)C,16,e,d,p,q,u,n);if (status < 0) /* modexp error? */

return status; /* return error status *//* Extract the signature */

status = rsa_public_decrypt((byte *)C,C,e,n);if (status < 0) /* modexp error? */

return status; /* return error status *//* Verify that we got the same thing back. */

Criptografía y Seguridad

Informática

Pretty Good Privacy Página45

if (status != 16)return KEYFAILED;

for (i = 0; i < 16; i++)if (((byte *)C)[i] != 3*i+7)

return KEYFAILED;}return 0; /* normal return */

} /* rsa_keygen */

/****************** End of RSA-specific routines *******************/

Criptografía y Seguridad

Informática

Pretty Good Privacy Página46

IDEA

/* * idea.c - C source code for IDEA block cipher. * IDEA (International Data Encryption Algorithm), formerly knownas * IPES (Improved Proposed Encryption Standard). * Algorithm developed by Xuejia Lai and James L. Massey, of ETHZurich. * This implementation modified and derived from original C code * developed by Xuejia Lai. * Zero-based indexing added, names changed from IPES to IDEA. * CFB functions added. Random number routines added. * * Extensively optimized and restructured by Colin Plumb. * * There are two adjustments that can be made to this code to * speed it up. Defaults may be used for PCs. Only the -DIDEA32 * pays off significantly if selectively set or not set. * Experiment to see what works best for your machine. * * Multiplication: default is inline, -DAVOID_JUMPS uses a * different version that does not do any conditional * jumps (a few percent worse on a SPARC), while * -DSMALL_CACHE takes it out of line to stay * within a small on-chip code cache. * Variables: normally, 16-bit variables are used, but some * machines (notably RISCs) do not have 16-bit registers, * so they do a great deal of masking. -DIDEA32 uses"int" * register variables and masks explicitly only where * necessary. On a SPARC, for example, this boosts * performace by 30%. * * The IDEA(tm) block cipher is covered by patents held by ETHand a * Swiss company called Ascom-Tech AG. The Swiss patent numberis * PCT/CH91/00117, the European patent number is EP 0 482 154 B1,and * the U.S. patent number is US005214703. IDEA(tm) is atrademark of * Ascom-Tech AG. There is no license fee required fornoncommercial * use. Commercial users may obtain licensing details fromDieter * Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502Solothurn, * Switzerland, Tel +41 65 242885, Fax +41 65 235761. * * The IDEA block cipher uses a 64-bit block size, and a 128-bitkey * size. It breaks the 64-bit cipher block into four 16-bitwords * because all of the primitive inner operations are done with16-bit * arithmetic. It likewise breaks the 128-bit cipher key intoeight

Criptografía y Seguridad

Informática

Pretty Good Privacy Página47

* 16-bit words. * * For further information on the IDEA cipher, see the book: * Xuejia Lai, "On the Design and Security of Block Ciphers", * ETH Series on Information Processing (ed. J.L. Massey) Vol1, * Hartung-Gorre Verlag, Konstanz, Switzerland, 1992. ISBN * 3-89191-573-X. * * This code runs on arrays of bytes by taking pairs in big-endian * order to make the 16-bit words that IDEA uses internally.This * produces the same result regardless of the byte order of the * native CPU. */

#include <string.h>#include "idea.h"#include "randpool.h"

#ifdef MACTC5#include <string.h>#define IDEA32#define SMALL_CACHE#define USE68ASMvoid ideaCipher(byte const inbuf[8], byte outbuf[8],

word16 const *key);#endif

#ifdef IDEA32 /* Use >16-bit temporaries */#define low16(x) ((x) & 0xFFFF)typedef unsigned int uint16; /* at LEAST 16 bits, maybe more */#else#define low16(x) (x) /* this is only ever applied to uint16's*/typedef word16 uint16;#endif

#ifdef _GNUC_/* __const__ simply means there are no side effects for this function, * which is useful info for the gcc optimizer */#define CONST __const__#else#define CONST#endif

/* * Multiplication, modulo (2**16)+1 * Note that this code is structured on the assumption that * untaken branches are cheaper than taken branches, and the * compiler doesn't schedule branches. */#ifdef SMALL_CACHE#ifdef MACTC5

CONST static uint16mul(uint16 a, uint16 b) {

Criptografía y Seguridad

Informática

Pretty Good Privacy Página48

asm {move.w a,d1beq.s @aeq0move.w b,d0beq.s @beq0mulu.w d0,d1 ; a = a * bmove.w d1,d0 ; b = aswap d1 ; a = a >> 16sub.w d1,d0 ; b = b - abcc.s @endit ; b >= a?addq.w #1,d0 ; b < a : (b - a) + 1bra.s @endit

@aeq0: moveq #1,d0move.w b,d1sub.w d1,d0 ; 1 - bbra.s @endit

@beq0: moveq #1,d0sub.w d1,d0 ; 1 - a}

endit: return;}

#else

CONST static uint16 mul(register uint16 a, register uint16 b){ register word32 p;

p = (word32) a *b; if (p) {

b = low16(p);a = p >> 16;return (b - a) + (b < a);

} else if (a) {return 1 - a;

} else {return 1 - b;

}} /* mul */#endif /* MACTC5 */#endif /* SMALL_CACHE */

/* * Compute the multiplicative inverse of x, modulo 65537, usingEuclid's * algorithm. It is unrolled twice to avoid swapping the registerseach * iteration, and some subtracts of t have been changed to adds. */CONST static uint16 mulInv(uint16 x){ uint16 t0, t1; uint16 q, y;

if (x <= 1)return x; /* 0 and 1 are self-inverse */

Criptografía y Seguridad

Informática

Pretty Good Privacy Página49

t1 = 0x10001L / x; /* Since x >= 2, this fits into 16 bits*/ y = 0x10001L % x; if (y == 1)

return low16(1 - t1); t0 = 1; do {

q = x / y;x = x % y;t0 += q * t1;if (x == 1) return t0;q = y / x;y = y % x;t1 += q * t0;

} while (y != 1); return low16(1 - t1);} /* mukInv */

/* * Expand a 128-bit user key to a working encryption key EK */static void ideaExpandKey(byte const *userkey, word16 * EK){ int i, j;

for (j = 0; j < 8; j++) {EK[j] = (userkey[0] << 8) + userkey[1];userkey += 2;

} for (i = 0; j < IDEAKEYLEN; j++) {

i++;EK[i + 7] = EK[i & 7] << 9 | EK[i + 1 & 7] >> 7;EK += i & 8;i &= 7;

}} /* ideaExpandKey */

/* * Compute IDEA decryption key DK from an expanded IDEA encryption keyEK * Note that the input and output may be the same. Thus, the key is * inverted into an internal buffer, and then copied to the output. */static void ideaInvertKey(word16 const *EK, word16 DK[IDEAKEYLEN]){ int i; uint16 t1, t2, t3; word16 temp[IDEAKEYLEN]; word16 *p = temp + IDEAKEYLEN;

t1 = mulInv(*EK++); t2 = -*EK++; t3 = -*EK++; *--p = mulInv(*EK++); *--p = t3; *--p = t2; *--p = t1;

Criptografía y Seguridad

Informática

Pretty Good Privacy Página50

for (i = 0; i < IDEAROUNDS - 1; i++) {t1 = *EK++;*--p = *EK++;*--p = t1;

t1 = mulInv(*EK++);t2 = -*EK++;t3 = -*EK++;*--p = mulInv(*EK++);*--p = t2;*--p = t3;*--p = t1;

} t1 = *EK++; *--p = *EK++; *--p = t1;

t1 = mulInv(*EK++); t2 = -*EK++; t3 = -*EK++; *--p = mulInv(*EK++); *--p = t3; *--p = t2; *--p = t1;/* Copy and destroy temp copy */ memcpy(DK, temp, sizeof(temp)); burn(temp);} /* ideaInvertKey */

/* * MUL(x,y) computes x = x*y, modulo 0x10001. Requires two temps, * t16 and t32. x is modified, and must be a side-effect-free lvalue. * y may be anything, but unlike x, must be strictly less than 65536 * even if low16() is #defined. * All of these are equivalent - see which is faster on your machine */#ifdef SMALL_CACHE#define MUL(x,y) (x = mul(low16(x),y))#else /* !SMALL_CACHE */#ifdef AVOID_JUMPS#define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1), \

t32 = (word32)x*t16 + x + t16, x = low16(t32), \t16 = t32>>16, x = (x-t16) + (x<t16) + 1)

#else /* !AVOID_JUMPS (default) */#define MUL(x,y) \

((t16 = (y)) ? \(x=low16(x)) ? \

t32 = (word32)x*t16, \x = low16(t32), \t16 = t32>>16, \x = (x-t16)+(x<t16) \

: \(x = 1-t16) \

: \(x = 1-x))

#endif#endif

/* IDEA encryption/decryption algorithm */

Criptografía y Seguridad

Informática

Pretty Good Privacy Página51

/* Note that in and out can be the same buffer */#ifndef USE68ASMstatic void ideaCipher(byte const inbuf[8], byte outbuf[8],

word16 const *key){ register uint16 x1, x2, x3, x4, s2, s3; word16 *in, *out;#ifndef SMALL_CACHE register uint16 t16; /* Temporaries needed by MUL macro */ register word32 t32;#endif int r = IDEAROUNDS;

in = (word16 *) inbuf; x1 = *in++; x2 = *in++; x3 = *in++; x4 = *in;#ifndef HIGHFIRST x1 = (x1 >> 8) | (x1 << 8); x2 = (x2 >> 8) | (x2 << 8); x3 = (x3 >> 8) | (x3 << 8); x4 = (x4 >> 8) | (x4 << 8);#endif do {

MUL(x1, *key++);x2 += *key++;x3 += *key++;MUL(x4, *key++);

s3 = x3;x3 ^= x1;MUL(x3, *key++);s2 = x2;x2 ^= x4;x2 += x3;MUL(x2, *key++);x3 += x2;

x1 ^= x2;x4 ^= x3;

x2 ^= s3;x3 ^= s2;

} while (--r); MUL(x1, *key++); x3 += *key++; x2 += *key++; MUL(x4, *key);

out = (word16 *) outbuf;#ifdef HIGHFIRST *out++ = x1; *out++ = x3; *out++ = x2; *out = x4;#else /* !HIGHFIRST */ x1 = low16(x1); x2 = low16(x2);

Criptografía y Seguridad

Informática

Pretty Good Privacy Página52

x3 = low16(x3); x4 = low16(x4); *out++ = (x1 >> 8) | (x1 << 8); *out++ = (x3 >> 8) | (x3 << 8); *out++ = (x2 >> 8) | (x2 << 8); *out = (x4 >> 8) | (x4 << 8);#endif} /* ideaCipher */#endif /* USE68ASM */

/*-------------------------------------------------------------*/

#ifdef TEST

#include <stdio.h>#include <time.h>/* * This is the number of Kbytes of test data to encrypt. * It defaults to 1 MByte. */#ifndef BLOCKS#ifndef KBYTES#define KBYTES 1024#endif#define BLOCKS (64*KBYTES)#endif

int main(void){ /* Test driver for IDEA cipher */ int i, j, k; byte userkey[16]; word16 EK[IDEAKEYLEN], DK[IDEAKEYLEN]; byte XX[8], YY[8], ZZ[8]; clock_t start, end; long l;

/* Make a sample user key for testing... */ for (i = 0; i < 16; i++)

userkey[i] = i + 1;

/* Compute encryption subkeys from user key... */ ideaExpandKey(userkey, EK); printf("\nEncryption key subblocks: "); for (j = 0; j < IDEAROUNDS + 1; j++) {

printf("\nround %d: ", j + 1);if (j < IDEAROUNDS) for (i = 0; i < 6; i++)

printf(" %6u", EK[j * 6 + i]);else for (i = 0; i < 4; i++)

printf(" %6u", EK[j * 6 + i]); }

/* Compute decryption subkeys from encryption subkeys... */ ideaInvertKey(EK, DK); printf("\nDecryption key subblocks: "); for (j = 0; j < IDEAROUNDS + 1; j++) {

printf("\nround %d: ", j + 1);if (j < IDEAROUNDS)

Criptografía y Seguridad

Informática

Pretty Good Privacy Página53

for (i = 0; i < 6; i++)printf(" %6u", DK[j * 6 + i]);

else for (i = 0; i < 4; i++)

printf(" %6u", DK[j * 6 + i]); }

/* Make a sample plaintext pattern for testing... */ for (k = 0; k < 8; k++)

XX[k] = k;

printf("\n Encrypting %d bytes (%ld blocks)...", BLOCKS * 16,BLOCKS); fflush(stdout); start = clock(); memcpy(YY, XX, 8); for (l = 0; l < BLOCKS; l++)

ideaCipher(YY, YY, EK); /* repeated encryption */ memcpy(ZZ, YY, 8); for (l = 0; l < BLOCKS; l++)

ideaCipher(ZZ, ZZ, DK); /* repeated decryption */ end = clock() - start; l = end / (CLOCKS_PER_SEC / 1000) + 1; i = l / 1000; j = l % 1000; l = (16 * BLOCKS * (CLOCKS_PER_SEC / 1000)) / (end / 1000); printf("%d.%03d seconds = %ld bytes per second\n", i, j, l);

printf("\nX %3u %3u %3u %3u %3u %3u %3u %3u\n", XX[0], XX[1], XX[2], XX[3], XX[4], XX[5], XX[6], XX[7]);

printf("\nY %3u %3u %3u %3u %3u %3u %3u %3u\n", YY[0], YY[1], YY[2], YY[3], YY[4], YY[5], YY[6], YY[7]);

printf("\nZ %3u %3u %3u %3u %3u %3u %3u %3u\n", ZZ[0], ZZ[1], ZZ[2], ZZ[3], ZZ[4], ZZ[5], ZZ[6], ZZ[7]);

/* Now decrypted ZZ should be same as original XX */ for (k = 0; k < 8; k++)

if (XX[k] != ZZ[k]) { printf("\n\07Error! Noninvertable encryption.\n"); exit(-1); /* error exit */}

printf("\nNormal exit.\n"); return 0; /* normal exit */} /* main */

#endif /* TEST */

/*************************************************************************/

void ideaCfbReinit(struct IdeaCfbContext *context, byte const *iv){ if (iv)

memcpy(context->iv, iv, 8); else

fill0(context->iv, 8); context->bufleft = 0;}

Criptografía y Seguridad

Informática

Pretty Good Privacy Página54

void ideaCfbInit(struct IdeaCfbContext *context, byte const key[16]){ ideaExpandKey(key, context->key); ideaCfbReinit(context, 0);}

void ideaCfbDestroy(struct IdeaCfbContext *context){ burn(*context);}

/* * Okay, explanation time: * Phil invented a unique way of doing CFB that's sensitive tosemantic * boundaries within the data being encrypted. One way to phrase * CFB en/decryption is to say that you XOR the current 8 bytes with * IDEA(previous 8 bytes of ciphertext). Normally, you repeat this * at 8-byte intervals, but Phil decided to resync things on the * boundaries between elements in the stream being encrypted. * * That is, the last 4 bytes of a 12-byte field are en/decrypted using * the first 4 bytes of IDEA(previous 8 bytes of ciphertext), but then * the last 4 bytes of that IDEA computation are thrown away, and the * first 8 bytes of the next field are en/decrypted using * IDEA(last 8 bytes of ciphertext). This is equivalent to using a * shorter feedback length (if you're familiar with the general CFB * technique) briefly, and doesn't weaken the cipher any (usingshorter * CFB lengths makes it stronger, actually), it just makes it a bitunusual. * * Anyway, to accomodate this behaviour, every time we do an IDEA * encrpytion of 8 bytes of ciphertext to get 8 bytes of XOR mask, * we remember the ciphertext. Then if we have to resync things * after having processed, say, 2 bytes, we refill the iv buffer * with the last 6 bytes of the old ciphertext followed by the * 2 bytes of new ciphertext stored in the front of the iv buffer. */void ideaCfbSync(struct IdeaCfbContext *context){ int bufleft = context->bufleft;

if (bufleft) {memmove(context->iv + bufleft, context->iv, 8 - bufleft);memcpy(context->iv, context->oldcipher + 8 - bufleft, bufleft);context->bufleft = 0;

}}

/* * Encrypt a buffer of data, using IDEA in CFB mode. * There are more compact ways of writing this, but this is * written for speed. */void ideaCfbEncrypt(struct IdeaCfbContext *context, byte const *src,

byte * dest, int count){

Criptografía y Seguridad

Informática

Pretty Good Privacy Página55

int bufleft = context->bufleft; byte *bufptr = context->iv + 8 - bufleft;

/* If there are no more bytes to encrypt that there are bytes * in the buffer, XOR them in and return. */ if (count <= bufleft) {

context->bufleft = bufleft - count;while (count--) { *dest++ = *bufptr++ ^= *src++;}return;

} count -= bufleft; /* Encrypt the first bufleft (0 to 7) bytes of the input by XOR * with the last bufleft bytes in the iv buffer. */ while (bufleft--) {

*dest++ = (*bufptr++ ^= *src++); } /* Encrypt middle blocks of the input by cranking the cipher, * XORing 8-byte blocks, and repeating until the count * is 8 or less. */ while (count > 8) {

bufptr = context->iv;memcpy(context->oldcipher, bufptr, 8);ideaCipher(bufptr, bufptr, context->key);bufleft = 8;count -= 8;do { *dest++ = (*bufptr++ ^= *src++);} while (--bufleft);

} /* Do the last 1 to 8 bytes */ bufptr = context->iv; memcpy(context->oldcipher, bufptr, 8); ideaCipher(bufptr, bufptr, context->key); context->bufleft = 8 - count; do {

*dest++ = (*bufptr++ ^= *src++); } while (--count);}

/* * Decrypt a buffer of data, using IDEA in CFB mode. * There are more compact ways of writing this, but this is * written for speed. */void ideaCfbDecrypt(struct IdeaCfbContext *context, byte const *src,

byte * dest, int count){ int bufleft = context->bufleft; static byte *bufptr; byte t;

bufptr = context->iv + (8 - bufleft); if (count <= bufleft) {

Criptografía y Seguridad

Informática

Pretty Good Privacy Página56

context->bufleft = bufleft - count;while (count--) { t = *bufptr; *dest++ = t ^ (*bufptr++ = *src++);}return;

} count -= bufleft; while (bufleft--) {

t = *bufptr;*dest++ = t ^ (*bufptr++ = *src++);

} while (count > 8) {

bufptr = context->iv;memcpy(context->oldcipher, bufptr, 8);ideaCipher(bufptr, bufptr, context->key);bufleft = 8;count -= 8;do { t = *bufptr; *dest++ = t ^ (*bufptr++ = *src++);} while (--bufleft);

} bufptr = context->iv; memcpy(context->oldcipher, bufptr, 8); ideaCipher(bufptr, bufptr, context->key); context->bufleft = 8 - count; do {

t = *bufptr;*dest++ = t ^ (*bufptr++ = *src++);

} while (--count);}

/********************************************************************/

/* * Cryptographically strong pseudo-random-number generator. * The design is from Appendix C of ANSI X9.17, "Financial * Institution Key Management (Wholesale)", with IDEA * substituted for the DES. */

/* * Initialize a cryptographic random-number generator. * key and seed should be arbitrary. */void ideaRandInit(struct IdeaRandContext *context, byte const key[16],

byte const seed[8]){ int i;

ideaExpandKey(key, context->key); context->bufleft = 0; memcpy(context->internalbuf, seed, 8);}

/* * Read out the RNG's state.

Criptografía y Seguridad

Informática

Pretty Good Privacy Página57

*/void ideaRandState(struct IdeaRandContext *context, byte key[16], byteseed[8]){ int i;

memcpy(seed, context->internalbuf, 8); for (i = 0; i < 8; i++) {

key[2 * i] = context->key[i] >> 8;key[2 * i + 1] = context->key[i];

}

}

/* * Encrypt the RNG's state with the given CFB encryptor. */void ideaRandWash(struct IdeaRandContext *context, structIdeaCfbContext *cfb){ byte keyseed[16 + 8]; int i;

ideaRandState(context, keyseed, keyseed + 16); ideaCfbEncrypt(cfb, keyseed, keyseed, 16 + 8); ideaRandInit(context, keyseed, keyseed + 16);

memset(keyseed, 0, 16 + 8);}

/* * Cryptographic pseudo-random-number generator, used for generating * session keys. */byteideaRandByte(struct IdeaRandContext *c){ int i;

if (!c->bufleft) {byte timestamp[8];

/* Get some true-random noise to help */randPoolGetBytes(timestamp, sizeof(timestamp));

/* Compute next 8 bytes of output */for (i = 0; i < 8; i++) c->outbuf[i] = c->internalbuf[i] ^ timestamp[i];ideaCipher(c->outbuf, c->outbuf, c->key);/* Compute new seed vector */for (i = 0; i < 8; i++) c->internalbuf[i] = c->outbuf[i] ^ timestamp[i];ideaCipher(c->internalbuf, c->internalbuf, c->key);burn(timestamp);c->bufleft = 8;

} return c->outbuf[--c->bufleft];}

Criptografía y Seguridad

Informática

Pretty Good Privacy Página58

/* end of idea.c */

Criptografía y Seguridad

Informática

Pretty Good Privacy Página59

MD5

/* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */#include <string.h> /* for memcpy() */#include "md5.h"

#ifndef HIGHFIRST#define byteReverse(buf, len) /* Nothing */#elsevoid byteReverse(unsigned char *buf, unsigned longs);

#ifndef ASM_MD5/* * Note: this code is harmless on little-endian machines. */void byteReverse(unsigned char *buf, unsigned longs){ uint32 t; do {

t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]);*(uint32 *) buf = t;buf += 4;

} while (--longs);}#endif#endif

/* * Start MD5 accumulation. Set bit count to 0 and buffer tomysterious * initialization constants. */void MD5Init(struct MD5Context *ctx){ ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476;

ctx->bits[0] = 0; ctx->bits[1] = 0;}

Criptografía y Seguridad

Informática

Pretty Good Privacy Página60

/* * Update context to reflect the concatenation of another buffer full * of bytes. */void MD5Update(struct MD5Context *ctx, unsigned char const *buf,unsigned len){ uint32 t;

/* Update bitcount */

t = ctx->bits[0]; if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)

ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29;

t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */

/* Handle any leading odd-sized chunks */

if (t) {unsigned char *p = (unsigned char *) ctx->in + t;

t = 64 - t;if (len < t) { memcpy(p, buf, len); return;}memcpy(p, buf, t);byteReverse(ctx->in, 16);MD5Transform(ctx->buf, (uint32 *) ctx->in);buf += t;len -= t;

} /* Process data in 64-byte chunks */

while (len >= 64) {memcpy(ctx->in, buf, 64);byteReverse(ctx->in, 16);MD5Transform(ctx->buf, (uint32 *) ctx->in);buf += 64;len -= 64;

}

/* Handle any remaining bytes of data. */

memcpy(ctx->in, buf, len);}

/* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */void MD5Final(unsigned char digest[16], struct MD5Context *ctx){ unsigned count; unsigned char *p;

Criptografía y Seguridad

Informática

Pretty Good Privacy Página61

/* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F;

/* Set the first char of padding to 0x80. This is safe sincethere is always at least one byte free */ p = ctx->in + count; *p++ = 0x80;

/* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count;

/* Pad out to 56 mod 64 */ if (count < 8) {

/* Two lots of padding: Pad the first block to 64 bytes */memset(p, 0, count);byteReverse(ctx->in, 16);MD5Transform(ctx->buf, (uint32 *) ctx->in);

/* Now fill the next block with 56 bytes */memset(ctx->in, 0, 56);

} else {/* Pad block to 56 bytes */memset(p, 0, count - 8);

} byteReverse(ctx->in, 14);

/* Append length in bits and transform */ ((uint32 *) ctx->in)[14] = ctx->bits[0]; ((uint32 *) ctx->in)[15] = ctx->bits[1];

MD5Transform(ctx->buf, (uint32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */}

#ifndef ASM_MD5

/* The four core functions - F1 is optimized somewhat */

/* #define F1(x, y, z) (x & y | ~x & z) */#define F1(x, y, z) (z ^ (x & (y ^ z)))#define F2(x, y, z) F1(z, x, y)#define F3(x, y, z) (x ^ y ^ z)#define F4(x, y, z) (y ^ (x | ~z))

/* This is the central step in the MD5 algorithm. */#ifdef __PUREC__#define MD5STEP(f, w, x, y, z, data, s) \

( w += f /*(x, y, z)*/ + data, w = w<<s | w>>(32-s), w += x )#else#define MD5STEP(f, w, x, y, z, data, s) \

( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )#endif

/* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks

Criptografía y Seguridad

Informática

Pretty Good Privacy Página62

* the data and converts bytes into longwords for this routine. */void MD5Transform(uint32 buf[4], uint32 const in[16]){ register uint32 a, b, c, d;

a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3];

#ifdef __PUREC__ /* PureC Weirdness... (GG) */ MD5STEP(F1(b,c,d), a, b, c, d, in[0] + 0xd76aa478L, 7); MD5STEP(F1(a,b,c), d, a, b, c, in[1] + 0xe8c7b756L, 12); MD5STEP(F1(d,a,b), c, d, a, b, in[2] + 0x242070dbL, 17); MD5STEP(F1(c,d,a), b, c, d, a, in[3] + 0xc1bdceeeL, 22); MD5STEP(F1(b,c,d), a, b, c, d, in[4] + 0xf57c0fafL, 7); MD5STEP(F1(a,b,c), d, a, b, c, in[5] + 0x4787c62aL, 12); MD5STEP(F1(d,a,b), c, d, a, b, in[6] + 0xa8304613L, 17); MD5STEP(F1(c,d,a), b, c, d, a, in[7] + 0xfd469501L, 22); MD5STEP(F1(b,c,d), a, b, c, d, in[8] + 0x698098d8L, 7); MD5STEP(F1(a,b,c), d, a, b, c, in[9] + 0x8b44f7afL, 12); MD5STEP(F1(d,a,b), c, d, a, b, in[10] + 0xffff5bb1L, 17); MD5STEP(F1(c,d,a), b, c, d, a, in[11] + 0x895cd7beL, 22); MD5STEP(F1(b,c,d), a, b, c, d, in[12] + 0x6b901122L, 7); MD5STEP(F1(a,b,c), d, a, b, c, in[13] + 0xfd987193L, 12); MD5STEP(F1(d,a,b), c, d, a, b, in[14] + 0xa679438eL, 17); MD5STEP(F1(c,d,a), b, c, d, a, in[15] + 0x49b40821L, 22);

MD5STEP(F2(b,c,d), a, b, c, d, in[1] + 0xf61e2562L, 5); MD5STEP(F2(a,b,c), d, a, b, c, in[6] + 0xc040b340L, 9); MD5STEP(F2(d,a,b), c, d, a, b, in[11] + 0x265e5a51L, 14); MD5STEP(F2(c,d,a), b, c, d, a, in[0] + 0xe9b6c7aaL, 20); MD5STEP(F2(b,c,d), a, b, c, d, in[5] + 0xd62f105dL, 5); MD5STEP(F2(a,b,c), d, a, b, c, in[10] + 0x02441453L, 9); MD5STEP(F2(d,a,b), c, d, a, b, in[15] + 0xd8a1e681L, 14); MD5STEP(F2(c,d,a), b, c, d, a, in[4] + 0xe7d3fbc8L, 20); MD5STEP(F2(b,c,d), a, b, c, d, in[9] + 0x21e1cde6L, 5); MD5STEP(F2(a,b,c), d, a, b, c, in[14] + 0xc33707d6L, 9); MD5STEP(F2(d,a,b), c, d, a, b, in[3] + 0xf4d50d87L, 14); MD5STEP(F2(c,d,a), b, c, d, a, in[8] + 0x455a14edL, 20); MD5STEP(F2(b,c,d), a, b, c, d, in[13] + 0xa9e3e905L, 5); MD5STEP(F2(a,b,c), d, a, b, c, in[2] + 0xfcefa3f8L, 9); MD5STEP(F2(d,a,b), c, d, a, b, in[7] + 0x676f02d9L, 14); MD5STEP(F2(c,d,a), b, c, d, a, in[12] + 0x8d2a4c8aL, 20);

MD5STEP(F3(b,c,d), a, b, c, d, in[5] + 0xfffa3942L, 4); MD5STEP(F3(a,b,c), d, a, b, c, in[8] + 0x8771f681L, 11); MD5STEP(F3(d,a,b), c, d, a, b, in[11] + 0x6d9d6122L, 16); MD5STEP(F3(c,d,a), b, c, d, a, in[14] + 0xfde5380cL, 23); MD5STEP(F3(b,c,d), a, b, c, d, in[1] + 0xa4beea44L, 4); MD5STEP(F3(a,b,c), d, a, b, c, in[4] + 0x4bdecfa9L, 11); MD5STEP(F3(d,a,b), c, d, a, b, in[7] + 0xf6bb4b60L, 16); MD5STEP(F3(c,d,a), b, c, d, a, in[10] + 0xbebfbc70L, 23); MD5STEP(F3(b,c,d), a, b, c, d, in[13] + 0x289b7ec6L, 4); MD5STEP(F3(a,b,c), d, a, b, c, in[0] + 0xeaa127faL, 11); MD5STEP(F3(d,a,b), c, d, a, b, in[3] + 0xd4ef3085L, 16); MD5STEP(F3(c,d,a), b, c, d, a, in[6] + 0x04881d05L, 23); MD5STEP(F3(b,c,d), a, b, c, d, in[9] + 0xd9d4d039L, 4);

Criptografía y Seguridad

Informática

Pretty Good Privacy Página63

MD5STEP(F3(a,b,c), d, a, b, c, in[12] + 0xe6db99e5L, 11); MD5STEP(F3(d,a,b), c, d, a, b, in[15] + 0x1fa27cf8L, 16); MD5STEP(F3(c,d,a), b, c, d, a, in[2] + 0xc4ac5665L, 23);

MD5STEP(F4(b,c,d), a, b, c, d, in[0] + 0xf4292244L, 6); MD5STEP(F4(a,b,c), d, a, b, c, in[7] + 0x432aff97L, 10); MD5STEP(F4(d,a,b), c, d, a, b, in[14] + 0xab9423a7L, 15); MD5STEP(F4(c,d,a), b, c, d, a, in[5] + 0xfc93a039L, 21); MD5STEP(F4(b,c,d), a, b, c, d, in[12] + 0x655b59c3L, 6); MD5STEP(F4(a,b,c), d, a, b, c, in[3] + 0x8f0ccc92L, 10); MD5STEP(F4(d,a,b), c, d, a, b, in[10] + 0xffeff47dL, 15); MD5STEP(F4(c,d,a), b, c, d, a, in[1] + 0x85845dd1L, 21); MD5STEP(F4(b,c,d), a, b, c, d, in[8] + 0x6fa87e4fL, 6); MD5STEP(F4(a,b,c), d, a, b, c, in[15] + 0xfe2ce6e0L, 10); MD5STEP(F4(d,a,b), c, d, a, b, in[6] + 0xa3014314L, 15); MD5STEP(F4(c,d,a), b, c, d, a, in[13] + 0x4e0811a1L, 21); MD5STEP(F4(b,c,d), a, b, c, d, in[4] + 0xf7537e82L, 6); MD5STEP(F4(a,b,c), d, a, b, c, in[11] + 0xbd3af235L, 10); MD5STEP(F4(d,a,b), c, d, a, b, in[2] + 0x2ad7d2bbL, 15); MD5STEP(F4(c,d,a), b, c, d, a, in[9] + 0xeb86d391L, 21);#else MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);

MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);

MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);

Criptografía y Seguridad

Informática

Pretty Good Privacy Página64

MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);

MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);#endif

buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d;}

#endif

Criptografía y Seguridad

Informática

Pretty Good Privacy Página65

SHA.

---- SHS.H ----

#ifndef _SHS_DEFINED

#define _SHS_DEFINED

/* Some useful types */

typedef unsigned char BYTE;typedef unsigned int WORD;typedef unsigned long LONG;

/* Exit status of functions. */

#define OK 0#define ERROR -1

/* Define the following to use the updated SHS implementation */

#define NEW_SHS /**/

/* Define the following if running on a little-endian CPU */

#define LITTLE_ENDIAN /**/

/* The SHS block size and message digest sizes, in bytes */

#define SHS_DATASIZE 64#define SHS_DIGESTSIZE 20

/* The structure for storing SHS info */

typedef struct { LONG digest[ 5 ]; /* Message digest */ LONG countLo, countHi; /* 64-bit bit count */ LONG data[ 16 ]; /* SHS data buffer */ } SHS_INFO;

/* Message digest functions */

void shsInit( SHS_INFO *shsInfo );void shsUpdate( SHS_INFO *shsInfo, BYTE *buffer, int count );void shsFinal( SHS_INFO *shsInfo );

#endif /* _SHS_DEFINED */

---- SHS.C ----

#include <string.h>#include "shs.h"

/* The SHS f()-functions. The f1 and f3 functions can be optimized to save one boolean operation each - thanks to Rich Schroeppel, [email protected] for discovering this */

Criptografía y Seguridad

Informática

Pretty Good Privacy Página66

/*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) // Rounds 0-19 */#define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 *//*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) // Rounds40-59 */#define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */

/* The SHS Mysterious Constants */

#define K1 0x5A827999L /* Rounds 0-19 */#define K2 0x6ED9EBA1L /* Rounds 20-39 */#define K3 0x8F1BBCDCL /* Rounds 40-59 */#define K4 0xCA62C1D6L /* Rounds 60-79 */

/* SHS initial values */

#define h0init 0x67452301L#define h1init 0xEFCDAB89L#define h2init 0x98BADCFEL#define h3init 0x10325476L#define h4init 0xC3D2E1F0L

/* Note that it may be necessary to add parentheses to these macros ifthey are to be called with expressions as arguments */

/* 32-bit rotate left - kludged with shifts */

#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )

/* The initial expanding function. The hash function is defined overan 80-word expanded input array W, where the first 16 are copies ofthe input data, and the remaining 64 are defined by

W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ]

This implementation generates these values on the fly in a circular buffer - thanks to Colin Plumb, [email protected] for this optimization.

The updated SHS changes the expanding function by adding a rotateof 1 bit. Thanks to Jim Gillogly, [email protected], and an anonymouscontributor for this information */

Criptografía y Seguridad

Informática

Pretty Good Privacy Página67

#ifdef NEW_SHS #define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ i -14 & 15 ] ^ \ W[ i - 8 & 15 ] ^ W[i - 3 & 15 ] ) ) )#else #define expand(W,i) ( W[ i & 15 ] ^= W[ i - 14 & 15 ] ^ W[ i - 8 &15 ] ^ W[ i - 3 & 15] )#endif /* NEW_SHS */

/* The prototype SHS sub-round. The fundamental sub-round is:

a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; b' = a; c' = ROTL( 30, b ); d' = c; e' = d;

but this is implemented by unrolling the loop 5 times and renamingthe variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) eachiteration. This code is then replicated 20 times for each of the 4 functions,using the next 20 values from the W[] array each time */

#define subRound(a, b, c, d, e, f, k, data) \ ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )

/* Initialize the SHS values */

void shsInit( SHS_INFO *shsInfo ) { /* Set the h-vars to their initial values */ shsInfo->digest[ 0 ] = h0init; shsInfo->digest[ 1 ] = h1init; shsInfo->digest[ 2 ] = h2init; shsInfo->digest[ 3 ] = h3init; shsInfo->digest[ 4 ] = h4init;

/* Initialise bit count */ shsInfo->countLo = shsInfo->countHi = 0; }

#ifndef ASM_SHS

/* Perform the SHS transformation. Note that this code, like MD5,seems to break some optimizing compilers due to the complexity of theexpressions and the size of the basic block. It may be necessary to split itinto sections, e.g. based on the four subrounds

Note that this corrupts the shsInfo->data area */

void SHSTransform( LONG *digest, LONG *data ) {

Criptografía y Seguridad

Informática

Pretty Good Privacy Página68

LONG A, B, C, D, E; /* Local vars */ LONG eData[ 16 ]; /* Expanded data */

/* Set up first buffer and local data buffer */ A = digest[ 0 ]; B = digest[ 1 ]; C = digest[ 2 ]; D = digest[ 3 ]; E = digest[ 4 ]; memcpy( eData, data, SHS_DATASIZE );

/* Heavy mangling, in 4 sub-rounds of 20 interations each. */ subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); subRound( D, E, A, B, C, f1, K1, eData[ 2 ] ); subRound( C, D, E, A, B, f1, K1, eData[ 3 ] ); subRound( B, C, D, E, A, f1, K1, eData[ 4 ] ); subRound( A, B, C, D, E, f1, K1, eData[ 5 ] ); subRound( E, A, B, C, D, f1, K1, eData[ 6 ] ); subRound( D, E, A, B, C, f1, K1, eData[ 7 ] ); subRound( C, D, E, A, B, f1, K1, eData[ 8 ] ); subRound( B, C, D, E, A, f1, K1, eData[ 9 ] ); subRound( A, B, C, D, E, f1, K1, eData[ 10 ] ); subRound( E, A, B, C, D, f1, K1, eData[ 11 ] ); subRound( D, E, A, B, C, f1, K1, eData[ 12 ] ); subRound( C, D, E, A, B, f1, K1, eData[ 13 ] ); subRound( B, C, D, E, A, f1, K1, eData[ 14 ] ); subRound( A, B, C, D, E, f1, K1, eData[ 15 ] ); subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) ); subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) ); subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) ); subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) );

subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) ); subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) ); subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) ); subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) ); subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) ); subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) ); subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) ); subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) ); subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) ); subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) ); subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) ); subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) ); subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) ); subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) ); subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) ); subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) ); subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) ); subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) ); subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) ); subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) );

subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) ); subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) ); subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) ); subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) ); subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) );

Criptografía y Seguridad

Informática

Pretty Good Privacy Página69

subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) ); subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) ); subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) ); subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) ); subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) ); subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) ); subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) ); subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) ); subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) ); subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) ); subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) ); subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) ); subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) ); subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) ); subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) );

subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) ); subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) ); subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) ); subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) ); subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) ); subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) ); subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) ); subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) ); subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) ); subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) ); subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) ); subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) );

/* Build message digest */ digest[ 0 ] += A; digest[ 1 ] += B; digest[ 2 ] += C; digest[ 3 ] += D; digest[ 4 ] += E; }#else void SHSTransform( LONG *digest, LONG *data );#endif /* !ASM_SHS */

/* When run on a little-endian CPU we need to perform byte reversal onan array of longwords. It is possible to make the code endianness- independant by fiddling around with data at the byte level, butthis makes for very slow code, so we rely on the user to sort outendianness at compile time */

#if defined( LITTLE_ENDIAN )

Criptografía y Seguridad

Informática

Pretty Good Privacy Página70

void longReverse( LONG *buffer, int byteCount ) { LONG value;

byteCount /= sizeof( LONG ); while( byteCount-- ) { value = *buffer; value = ( ( value & 0xFF00FF00L ) >> 8 ) | \ ( ( value & 0x00FF00FFL ) << 8 ); *buffer++ = ( value << 16 ) | ( value >> 16 ); } }#else #define longReverse(buf, count)#endif /* LITTLE_ENDIAN */

/* Update SHS for a block of data */

void shsUpdate( SHS_INFO *shsInfo, BYTE *buffer, int count ) { LONG tmp; int dataCount;

/* Update bitcount */ tmp = shsInfo->countLo; if ( ( shsInfo->countLo = tmp + ( ( LONG ) count << 3 ) ) < tmp ) shsInfo->countHi++; /* Carry from low to high */ shsInfo->countHi += count >> 29;

/* Get count of bytes already in data */ dataCount = ( int ) ( tmp >> 3 ) & 0x3F;

/* Handle any leading odd-sized chunks */ if( dataCount ) { BYTE *p = ( BYTE * ) shsInfo->data + dataCount;

dataCount = SHS_DATASIZE - dataCount; if( count < dataCount ) { memcpy( p, buffer, count ); return; } memcpy( p, buffer, dataCount ); longReverse( shsInfo->data, SHS_DATASIZE ); SHSTransform( shsInfo->digest, shsInfo->data ); buffer += dataCount; count -= dataCount; }

/* Process data in SHS_DATASIZE chunks */ while( count >= SHS_DATASIZE ) { memcpy( shsInfo->data, buffer, SHS_DATASIZE ); longReverse( shsInfo->data, SHS_DATASIZE ); SHSTransform( shsInfo->digest, shsInfo->data ); buffer += SHS_DATASIZE; count -= SHS_DATASIZE;

Criptografía y Seguridad

Informática

Pretty Good Privacy Página71

}

/* Handle any remaining bytes of data. */ memcpy( shsInfo->data, buffer, count ); }

/* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bitpattern 1 0* (64-bit count of bits processed, MSB-first) */

void shsFinal( SHS_INFO *shsInfo ) { int count; BYTE *dataPtr;

/* Compute number of bytes mod 64 */ count = ( int ) shsInfo->countLo; count = ( count >> 3 ) & 0x3F;

/* Set the first char of padding to 0x80. This is safe sincethere is always at least one byte free */ dataPtr = ( BYTE * ) shsInfo->data + count; *dataPtr++ = 0x80;

/* Bytes of padding needed to make 64 bytes */ count = SHS_DATASIZE - 1 - count;

/* Pad out to 56 mod 64 */ if( count < 8 ) { /* Two lots of padding: Pad the first block to 64 bytes */ memset( dataPtr, 0, count ); longReverse( shsInfo->data, SHS_DATASIZE ); SHSTransform( shsInfo->digest, shsInfo->data );

/* Now fill the next block with 56 bytes */ memset( shsInfo->data, 0, SHS_DATASIZE - 8 ); } else /* Pad block to 56 bytes */ memset( dataPtr, 0, count - 8 );

/* Append length in bits and transform */ shsInfo->data[ 14 ] = shsInfo->countHi; shsInfo->data[ 15 ] = shsInfo->countLo;

longReverse( shsInfo->data, SHS_DATASIZE - 8 ); SHSTransform( shsInfo->digest, shsInfo->data ); }

Criptografía y Seguridad

Informática

Pretty Good Privacy Página72

/******************************************************************************* SHS Test Code*******************************************************************************/

#include <stdio.h>#include <stdlib.h>#include <time.h>

/* Test the SHS implementation */

#ifdef NEW_SHS

static LONG shsTestResults[][ 5 ] = { { 0xA9993E36L, 0x4706816AL, 0xBA3E2571L, 0x7850C26CL, 0x9CD0D89DL,}, { 0x84983E44L, 0x1C3BD26EL, 0xBAAE4AA1L, 0xF95129E5L, 0xE54670F1L,}, { 0x34AA973CL, 0xD4C4DAA4L, 0xF61EEB2BL, 0xDBAD2731L, 0x6534016FL,} };

#else

static LONG shsTestResults[][ 5 ] = { { 0x0164B8A9L, 0x14CD2A5EL, 0x74C4F7FFL, 0x082C4D97L, 0xF1EDF880L}, { 0xD2516EE1L, 0xACFA5BAFL, 0x33DFC1C4L, 0x71E43844L, 0x9EF134C8L}, { 0x3232AFFAL, 0x48628A26L, 0x653B5AAAL, 0x44541FD9L, 0x0D690603L} };#endif /* NEW_SHS */

static int compareSHSresults( SHS_INFO *shsInfo, int shsTestLevel ) { int i;

/* Compare the returned digest and required values */ for( i = 0; i < 5; i++ ) if( shsInfo->digest[ i ] != shsTestResults[ shsTestLevel ][ i] ) return( ERROR ); return( OK ); }

void main( void ) { SHS_INFO shsInfo; unsigned int i; time_t secondCount; BYTE data[ 200 ];

Criptografía y Seguridad

Informática

Pretty Good Privacy Página73

/* Make sure we've got the endianness set right. If the machineis big-endian (up to 64 bits) the following value will be signed, otherwise it will be unsigned. Unfortunately we can't test forodd things like middle-endianness without knowing the size of thedata types */#ifdef LITTLE_ENDIAN if( *( long * ) "\x80\x00\x00\x00\x00\x00\x00\x00" < 0 ) { puts( "Error: Uncomment the LITTLE_ENDIAN define in SHS.H andrecompile" ); exit( ERROR ); }#else if( *( long * ) "\x80\x00\x00\x00\x00\x00\x00\x00" >= 0 ) { puts( "Error: Comment out the LITTLE_ENDIAN define in SHS.Hand recompile" ); exit( ERROR ); }#endif /* LITTLE_ENDIAN */

/* Test SHS against values given in SHS standards document */ printf( "Running SHS test 1 ... " ); shsInit( &shsInfo ); shsUpdate( &shsInfo, ( BYTE * ) "abc", 3 ); shsFinal( &shsInfo ); if( compareSHSresults( &shsInfo, 0 ) == ERROR ) { putchar( '\n' ); puts( "SHS test 1 failed" ); exit( ERROR ); }#ifdef NEW_SHS puts( "passed, result= A9993E364706816ABA3E25717850C26C9CD0D89D");#else puts( "passed, result= 0164B8A914CD2A5E74C4F7FF082C4D97F1EDF880");#endif /* NEW_SHS */

printf( "Running SHS test 2 ... " ); shsInit( &shsInfo ); shsUpdate( &shsInfo, ( BYTE * )"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56 ); shsFinal( &shsInfo ); if( compareSHSresults( &shsInfo, 1 ) == ERROR ) { putchar( '\n' ); puts( "SHS test 2 failed" ); exit( ERROR ); }#ifdef NEW_SHS puts( "passed, result= 84983E441C3BD26EBAAE4AA1F95129E5E54670F1");#else

Criptografía y Seguridad

Informática

Pretty Good Privacy Página74

puts( "passed, result= D2516EE1ACFA5BAF33DFC1C471E438449EF134C8");#endif /* NEW_SHS */

printf( "Running SHS test 3 ... " ); shsInit( &shsInfo ); for( i = 0; i < 15625; i++ ) shsUpdate( &shsInfo, ( BYTE * )"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64); shsFinal( &shsInfo ); if( compareSHSresults( &shsInfo, 2 ) == ERROR ) { putchar( '\n' ); puts( "SHS test 3 failed" ); exit( ERROR ); }#ifdef NEW_SHS puts( "passed, result= 34AA973CD4C4DAA4F61EEB2BDBAD27316534016F");#else puts( "passed, result= 3232AFFA48628A26653B5AAA44541FD90D690603");#endif /* NEW_SHS */

printf( "\nTesting speed for 10MB data... " ); shsInit( &shsInfo ); secondCount = time( NULL ); for( i = 0; i < 50000U; i++ ) shsUpdate( &shsInfo, data, 200 ); secondCount = time( NULL ) - secondCount; printf( "done. Time = %ld seconds, %ld kbytes/second\n", \ secondCount, 10050L / secondCount );

puts( "\nAll SHS tests passed" ); exit( OK ); }

Criptografía y Seguridad

Informática

Pretty Good Privacy Página75

Referencias.

http://www.arnal.es/free/cripto/pgp/algor.htmhttp://www.iie.edu.uy/~mazzara/pgphttp://www.ugr.es/~aquiran/cripto/cripto.htmhttp://geocities.com/CapeCanaveral/2566/pgp/pgp1.htmlhttp://www.kriptopolis.com