Cómo implementar el algoritmo RSA en C
lt;conceptos básicos
El algoritmo RSA es muy simple. se resume de la siguiente manera:
Encontrar Encuentra dos números primos p y q
Tomar n=p*q
Tomar t=(p-1)*(q -1)
Tome cualquier Se requiere un número e para satisfacer elt, y e y t son primos relativos (es decir, el máximo común divisor es 1)
Tome cualquier número e que satisfaga los requisitos de elt, y e y t son primos relativos (es decir, el máximo común divisor es 1) es 1)
Tome d*et==1
El resultado tiene tres números. : n d e
Establezca la información en el número M (M lt; n)
Establezca c=(M**d)n, obtenga la información cifrada c
Establecer m=(c)
Establecer m=(c)n, obtener la información cifrada c.
Nota: ** representa la potencia de dos, y d y e en las dos ecuaciones anteriores se pueden intercambiar.
En cifrado simétrico:
n d dos números constituyen una clave pública, que se puede comunicar a otros
n e dos números constituyen una clave privada, e es; guardado por uno mismo, nadie puede saberlo.
La información enviada a otros se cifra con e. Siempre que otros puedan descifrarla con d, demuestra que la información fue enviada por usted, lo que constituye un mecanismo de firma.
Otros te envían mensajes cifrados con d, por lo que sólo tú con e puedes descifrar el mensaje.
La seguridad de rsa es que para números grandes n, no existe una forma efectiva de descomponerlo.
Por lo tanto, si conoce n d, no puede obtener e si conoce n Par; si hay una e, no se puede obtener d.
lt;二GT;Ejercicio
A continuación, haremos un ejercicio:
Comprende cómo funciona:
Echa un vistazo Mira a dos personas que te envían mensajes para ver cómo funciona.
Encuentra dos números primos:
p=47
q=59
De esta manera
n= p*q=2773
t=(p-1)*(q-1)=2668
Tome e=63, que satisface elt y es consistente con e y t Números mutuamente primos
Usa Perl para realizar una enumeración exhaustiva simple. Puedes usar el número completo e*dt == 1 para obtener el número d:
C:\Tempgt; perl -e "foreach $i (1..9999){ print($i),last if $i*632668==1 }"
847
Es decir, d = 847
Finalmente tenemos la clave
n=2773
d=847
e=63
Con la información M=244 como Por ejemplo, echemos un vistazo
Cifrado:
c=M**dn = 244**8472773
Usar perl's cálculo de números grandes:
C:\Tempgt; perl -Mbigint -e "print 244**8472773"
465
es decir, use d para cifrar M y obtener la información cifrada c = 465
Descifrado:
Podemos descifrar la c cifrada restaurando M usando e:
m=c** es =465**632773:
C:\Tempgt; perl -Mbigint -e "print 465**632773"
244
Es decir, use e para descifrar c y obtener m = 244, que es igual a la Información M original.
lt; IIIgt; Cifrado de cadenas
Combinado con el proceso anterior, podemos implementar un ejemplo de cifrado y descifrado de cadenas.
Tome el valor ascii de un carácter en la cadena cada vez y calcúlelo como M. La salida es una cadena de números hexadecimales cifrados
Un número en forma de 3 bytes, como 01F
El código es el siguiente:
#! /usr/bin/perl -w
El programa de aprendizaje del proceso de cálculo #RSA está escrito como un programa de prueba
#watercloud 2003-8-12
#
usa estricto;
usa Math::BigInt;
mi RSA_ CORE = (n=gt; 2773, e=gt; 63, d=gt; 847) ; #p=47, q=59
mi $N=nueva Matemática::BigInt($RSA_CORE{n});
mi $E=nueva Matemática:: BigInt( $RSA_CORE{e});
mi $D=new Math::BigInt($RSA_CORE{d});
print "N=$N D=$D E= $E \n";
sub RSA_ENCRYPT
{
mi $r_mess = shift @_;
mi ($c, $i ,$M,$C,$cmess);
for($i=0;$i lt; longitud($$r_mess);$i )
{
$c=ord(substr($$r_mess, $i, 1));
$M=Math.:BigInt-gt; nuevo($c); >
$C=$M-gt;copia(); $C-gt;bmodpow($D,$N);
$c=sprintf "03X",$C; p>
$cmess.=$c;
}
return \$cmess;
}
sub RSA_DECRYPT
{
mi $r_mess = shift @_;
mi ($c, $i, $M, $C, $dmess);
for($i=0;$i lt.length($$r_mess);$i =3)
{
$c=substr($$r_mess ,$ i, 3);
$c=hex($c);
$M=Math::BigInt-gt; nuevo($c);
$C=$M-gt; copiar(); $C-gt; bmodpow($E, $N); p> $dmess.=$c;
}
devuelve \$dmess;
}
mi $mess="RSA waaahahaahaahaahaaha~ ~~";
$mess=$ARGV[0] if @ARGV gt;= 1;
print "Cadena original:",$mess,"\n" ;
mi $r_cmess = RSA_ENCRYPT(\$mess);
imprimir "Cadena cifrada:",$$r_cmess,"\n";
mi $ r_dmess = RSA_DECRYPT($r_
cmess);
print "Cadena descifrada:",$$r_dmess,"\n";
#EOF
Pruébalo:
C:\Tempgt;perl 3393EC12F0A466E0AA9510D025D7BA0712DC3379F47D51C325D67B
Cadena descifrada: enfoque seguro (xfocus)
lt;fourgt; mejorar
Como se mencionó anteriormente, la seguridad de rsa proviene del hecho de que n es lo suficientemente grande y el n que usamos en nuestras pruebas es muy pequeño.
Podemos obtener N y D E suficientemente grandes mediante herramientas como RSAKit y RSATool.
Usando estas herramientas, podemos obtener los 1024 Bit n y D E para realizar pruebas:
N = 0x328C74784DF3119C526D18098EBEBEB943B599cee13CC2b5FCD15F90B66EC3A85F5005D
BDCDED9BDCB3C4C 265AF164AD55884D8278F79A6BFDAD5C4F017F9CCF1538D4C20134383B
47d80EC74B5D6346346346346346346346346346346346346346346346346346346 3463466346634663466346346634663466346634663466B9E E5AD2D7BE7ABFB36E37108dd60438941d2ed173CCA50E114705D7E2BC511951
d=0x10001
e=0xE760A3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C2995
4C5D8 43080E4919CA8CE08718C3B0930867A98F635EB9EA9200B25906D91B80A47B77324E66AFF2
C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC02373 4763DA1DCABE9861A4789BD782A592D2B
1965
Establecer información original
M= 0x11111111111122222222222233333333333
Para completar un cálculo de números tan grande, necesita usar una biblioteca de aritmética de números grandes, y es muy Perl fácil de usar para calcular:
A) Cifre M con d de la siguiente manera:
c=M***dn:
C:\Tempgt. perl - Mbigint -e "$x=Math::BigInt-gt;bmodpow(0x11111111111111222222222222233
33333333333, 0x10001, 0x328C74784DF31119C526D18098EBEBB943B00 32B 599CEE13CC2BCE7B5F
CD15F90B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7A6BFDAD55EDBC4F0
17F9CCF1538D4C2013433B383B47D 8 0EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD6
0438941D2ED173CCA50E114705D7E2BC511951);imprimir $x-gt;as_hex"
0x17b287be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b7 3 d2576bd
45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b
3028
f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91
f1834580c3f6d90898
es decir, la información cifrada con d is
c=0 be418c69ecd7c39227ab681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd
45692b007f3a2f7c5f5aa1d99ef3866af26a8e876712ed1d e26bc0a1dc67e247715caa6b
3028f9461a3b1533ec0cb476441465f10d8ad47452a12db0601c5e8beda686dd96d2acd59ea89b91
f1834580c3f6d90898
B) Utilice e para descifrar c de la siguiente manera:
m=c **en: >
C:\Tempgt; -Mbigint -e "$x=Math::BigInt-gt;bmodpow(0x17b287be418c69ecd7c39227ab
681ac422fcc84bb35d8a632543b304de288a8d4434b73d2576bd45692b007f3a2f7 5aa1d99ef3
866af26a8e876712ed1d4cc4b293e26bc0a1dc67e247715caa6b3028f9461a3b1533ec0cb4764414
65f10d8ad47452a12db0601 c5e8beda686dd 96d2acd59ea89b91f1834580c3f6d90898,0xE760A
3804ACDE1E8E3D7DC0197F9CEF6282EF552E8CEBBB7434B01CB19A9D87A3106DD28C523C29954C5D
86B36E943080E4919CA8CE08718C3B0930867A98F63 EB9EA9200B25906D91B80A47B77324E66AFF
2C4D70D8B1C69C50A9D8B4B7A3C9EE05FFF3A16AFC023731D80634763DA1DCABE9861A4789BD782A
592 1965,0x328c74784df31119c526d18098ebeb943b0032b599cee13cc2bce7b5fcd15f90
B66EC3A85F5005DBDCDED9BDFCB3C4C265AF164AD55884D8278F791C7 55EDBC4F017F9CCF
1538D4C2013433B383B47D80EC74B51276CA05B5D6346B9EE5AD2D7BE7ABFB36E37108DD60438941
D2ED173CCA50E114705D7E2BC511951); el cálculo tarda unos 5 segundos en mi máquina P4 1.6G)
>
Utilice e= 0x111111111111222222222223333333333 == M para obtener el m descifrado
C) La implementación habitual de RSA
RSA es simple y elegante, pero la velocidad de cálculo es lenta y se usa generalmente en cifrado. No se usa directamente para cifrar toda la información.
El escenario más común es generar aleatoriamente una clave de cifrado simétrica y luego usar la clave de cifrado simétrica para cifrar toda la información. La situación más común es generar aleatoriamente una clave de cifrado simétrica, luego usar un algoritmo de cifrado simétrico para cifrar la información y luego usar
RSA para cifrar la clave de cifrado recién cifrada.
Finalmente, cabe señalar que actualmente se ha demostrado que N menores de 1024 bits son inseguros
No utilice RSA menores de 1024 bits usted mismo, es mejor usar 2048 bits.
------------------------------------------- ---------------
Implementación simple del algoritmo RSA en código fuente JAVA:
nombre de archivo: RSA.java
/*
* Creado el 3 de marzo de 2005
*
* TODO Para cambiar la plantilla de este archivo generado, visite
* Ventana - Preferencias - Java - Estilo de código - Plantillas de código
*/
importar java.IOException
importar java.io.FileWriter
importar java.io.FileReader
importar java.io.StringTokenizer
/**
* @autor Steve
*
*
* TODO Para cambiar la plantilla para esta anotación de tipo generada, visite
* Ventana - Preferencias - Java - Estilo de código - Código Plantillas
*/
clase pública RSA {
/**
* BigInteger.private static final BigInteger ZERO = BigInteger.ZERO
/**
* BigInteger.ONE
*/
privado estático final BigInteger ONE = BigInteger.ONE
p >/**
* Pseudo BigInteger.ONE
*/
privado estático final BigInteger ONE = BigInteger.ONE;
/**
* Pseudo BigInteger.ONE/UTWO
*/
BigInteger final estático privado DOS = new BigInteger("2");
BigInteger myKey privado
BigInteger myMod privado
tamaño de bloque int privado
RSA público (clave BigInteger, BigInteger n, int; b ) {<
miClave = clave
miMod = n;
tamaño de bloque = b; p > public void encodeFile (nombre de archivo de cadena) {
byte[] bytes = nuevo byte[ blockSize / 8 1];
byte[] temp; int tempLen;
InputStream es = null;
Fi
leWriter escritor = null;
intente {
es = nuevo FileInputStream(nombre de archivo);
escritor = nuevo FileWriter(nombre de archivo ".enc"); p>
p>
}
catch (FileNotFoundException e1){
System .out.println("Archivo no encontrado: " nombre de archivo);
}
catch (IOException e1){
System.out.println("Archivo no encontrado: " nombre de archivo ".enc");
}
/**
* Escribe la información codificada en 'filename'.enc
*/
prueba {
while ((tempLen = is.read(bytes, 1, blockSize / 8)) gt; 0) {
for (int i = tempLen 1; i lt; bytes.length; i ) {
bytes[i] = 0;
}
escritor.write(encodeDecode( new BigInteger(bytes)) " "); >
}
}
catch (IOException e1) {
System.out.println("error al escribir en el archivo");
}
/**
* Cerrar el flujo de entrada y el escritor de archivos
*/
intentar { p>
es.close();
escritor.close();
}
captura (IOException e1) {
System.out.println("Error al cerrar el archivo.");
}
}
}
public void decodeFile (nombre de archivo de cadena) {
lector FileReader = nulo
OutputStream os = nulo
prueba {
lector = nuevo FileReader( nombre de archivo);
os = new FileOutputStream( filename.replaceAll(".enc", ".dec"));
}
catch (FileNotFoundException e1 ) {
if (lector == null)
System.out.println("Archivo no encontrado: " nombre de archivo
else
);System.out.println("El archivo no es f
sonido: " filename.replaceAll(".enc", "dec"));
}
BufferedReader br = new BufferedReader(lector);
int desplazamiento;
byte[] temp, toFile;
StringTokenizer st = null
prueba {
while (br.ready( )) {
st = new StringTokenizer(br.readLine());
while (st.hasMoreTokens()){
toFile = encodeDecode(new BigInteger(st.nextToken())).toByteArray();
System.out.println(toFile.length " x " (blockSize / 8));
if (toFile [0] == 0 amp; toFile.length ! = (blockSize / 8)) {
temp = nuevo byte[blockSize / 8];
offset = temp. longitud - toFile.length
if (toFile[0] == 0 amp; amp; toFile.length !length;
for (int i = toFile.length - 1; (i lt; = 0)) amp; ((i desplazamiento) lt; = 0) {
temp[i desplazamiento] = toFile[i];
}
toFile = temp;
}
/*if (toFile.length != ((blockSize / 8) 1)){
temp = nuevo byte[(blockSize / 8) 1];
System.out.println(toFile.length " x " temp.length
); for (int i = 1; i lt; temp.length; i) {
temp[i] = toFile[i - 1]
}
toFile = temp;
}
else
System.out.println(toFile.length " " ((bloque))).
longitud " " ((blockSize / 8) 1));*/
os.write(toFile);
}
}
}
catch (IOException e1) {
System.out.println("¿Algo para archivar?println("Algo salió mal");
}
/**
* Cerrar el flujo de datos
*/
prueba {
os.close ( );
lector.close( );
}
captura (IOException e1) {
System.out.println( "Error al cerrar el archivo.");
}
}
}
/**
* en lt;ttgt;baselt;/ttgt;^lt;supgt;lt;ttgt;powlt;/ttgt;lt;/supgt; Modularización
* Ejecutar lt;ttgt;modlt;/ttgt en el dominio
*
* @param base La base a elevar
* @param pow El poder de la base a elevar
* @param mod El dominio del módulo para realizar esta operación
* @return lt;ttgt;baselt;/ttgt;^lt;supgt;lt;ttgt;powlt;/ttgt;lt;/supgt ; inlt; ttgt;modlt;/ttgt; dentro del dominio del módulo
*/
public BigInteger encodeDecode(BigInteger base) {
BigInteger a = UNO;
BigInteger s = base;
BigInteger n = myKey;
while (!n.equals(ZERO)) {
if (!n.mod(DOS).equals(ZERO))
a = a.multiply(s).mod(myMod);
s = s .pow(2).mod( myMod);
n = n.divide(DOS); /p>
}
}