/****************************************************************************/ /* Cifrado de Hill con matrices 2x2 */ /* */ /* Jaime Suarez <mcripto@bigfoot.com> 2003 */ /* en http://elparaiso.mat.uned.es */ /****************************************************************************/ #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> long coef1(long,long); long coef2(long,long); long invmod(long a, long m); int main() { char *s,*t, op, ch, *pt; int a11,a12,a21,a22, idet, m11,m12,m21,m22, x1,x2,y1,y2; s=(char *)malloc(200); t=(char *)malloc(200); printf("Cifrado de Hill 2x2.\n"); /* Pedir datos y comprueba que la matriz es inversible */ do { printf("Cifrar (c) o descifrar (d): "); scanf("%c",&op); } while (op!='c' && op!='d'); printf("\nIntroduzca matriz de cifrado.\n"); printf("a11 = "); scanf("%d",&a11); printf("a12 = "); scanf("%d",&a12); printf("a21 = "); scanf("%d",&a21); printf("a22 = "); scanf("%d",&a22); if ( (idet=invmod(a11*a22-a12*a21,26)) == 0) { printf("La matriz no es inversible.\n"); return 1; } /* Pide el texto y suprime todos los caracteres no alfabéticos */ /* si el número de caracteres no es par se añade una X */ getchar(); printf("\nIntroduzca el texto que %s: ", (op=='c')?"cifrar":"descifrar"); fgets(s,200,stdin); pt=t; while ( (ch=*s++) !=0) { if (isalpha(ch)) *pt++=toupper(ch); } *pt='\0'; if (strlen(t)%2 != 0) strcat(t,"X"); /* Se usa la matriz inicial o la inversa según cifre o descifre */ if (op=='c') { m11=a11; m12=a12; m21=a21; m22=a22; } else { m11= a22*idet; m12=-a12*idet; m21=-a21*idet; m22= a11*idet; } /* Multiplicación de cada bloque por la matriz */ pt=t; while (*pt) { x1= *pt++; x1 -= 'A'; x2= *pt++; x2 -= 'A'; y1= (x1*m11 + x2*m21) %26; while(y1<0) y1+=26; y2= (x1*m12 + x2*m22) %26; while(y2<0) y2+=26; putchar(y1+'A'); putchar(y2+'A'); putchar(' '); } printf("\n"); return 0; } /*--------------------------------------------------------------------- Teorema de Bezout: si c=mcd(a,b) entonces existen enteros alfa y beta tales que c= alfa*a + beta*b ----------------------------------------------------------------------*/ long coef1(long a,long b) { if (a%b==0) return (0); else return (coef2(b,a%b)); } long coef2(long a, long b) { if (a%b==0) return(1); else return (coef1(b,a%b)- a/b *coef2(b,a%b)); } /*---------------------------------------------------------------------- Calculo del inverso modulo un entero. Suponiendo que 1=mcd(m,n) entonces existen enteros a y b tales que 1=m.a+n.b y por tanto a es un inverso de a mod n Devuelve el inverso de m modulo n o 0 si no es inversible. ----------------------------------------------------------------------*/ long invmod(long m,long n) { long a,b; a=coef1(m,n); b=coef2(m,n); if (m*a+n*b!=1) return 0; else return a; }