Foro de elhacker.net

Seguridad Informática => Criptografía => Mensaje iniciado por: LaiaxanIV en 29 Abril 2016, 17:46 pm



Título: RSA, obteniendo clave privada
Publicado por: LaiaxanIV en 29 Abril 2016, 17:46 pm
Buenas gente!
Tengo un problema a la hora de obtener la clave privada a través de la clave pública.
Código
  1. from Crypto.PublicKey import RSA
  2. import gmpy
  3.  
  4. pub = RSA.importKey("""-----BEGIN PUBLIC KEY-----
  5. MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQAA0kl7JrOq0XcvkdpibzgA
  6. x2kU/9bbd9FYS+yMqyMWTSTJOcB892YHCVtfRRdmUVJQXiWGQBq0mHmlMOREuHVb
  7. RIBrsOPNeWl4s1bu3RfY+UdlVQh4b696RkjY+EZjAwDrAtP2GKZ8xuKcnGbeyOoq
  8. SThjFxcwUpFyC6upDOhOy6pIVwIWe3DIlcuhHaw/963GN7fDJBzGr2cRunP3TYP6
  9. 4a7BtCNEVp8C4b5TaNJVb0jsrvRh5PHNlVMbCIRQGIzEn4l/X4y2sQfYCgV4Pwm7
  10. Vq5gzxgKgjVIgItOHqs9WCmA0PuMqB2A2l0qU1JPiR7DEh2FwUUdLn+deuz3bHTB
  11. AgMBAAE=
  12. -----END PUBLIC KEY-----""");
  13.  
  14. n = long(pub.n);
  15. e = long(pub.e);
  16. print n;
  17. print e;
  18.  
  19. p = 14188273085411836729;
  20. q = 280615323801319888452039197798402115977;
  21.  
  22. d = long(gmpy.invert(e,(p-1)*(q-1)))
  23. print d
  24. key = RSA.construct((n,e,d,p,q));
  25. print key.exportKey('PEM',pkcs=1);
  26. f1 = open("rsa.pem","wb")
  27. f1.write(key.exportKey('PEM',pkcs=1))
  28.  
  29. message = "Un mensaje cualquiera"
  30. signature = key.sign(message,'')
  31. print pub.verify(message,signature)
  32.  

La p y la q las he obtenido usando el Sage, para conseguir factorizar el modulo. El último print da false, y si cifro un mensaje y lo descifro tampoco parece estar correcto. No se que puedo estar haciendo mal...
Espero que me podais ayudar. Gracias


Título: Re: RSA, obteniendo clave privada
Publicado por: kub0x en 29 Abril 2016, 23:53 pm
Buenas LaiaxanIV,

he hecho un code en C# como prueba para cifrar/descifrar un número cualquiera. He de decir que la construcción de la clave privada 'd' la he hecho a mano utilizando el concepto de la multplicativa inversa, sin emplear el extended euclidean (el cual yo recomiendo).

Para calcular la clave privada simplemente calculamos la inversa de 'e' en 'phi' ((p-1).(q-1)). Y me dirás, joe pero en tu método tienes que saber el totient de phi, phi((p-1).(q-1)), por lo tanto tienes que conocer la factorización de (p-1).(q-1). Claro, pero en este ejemplo es trivial calcularlo, porque son números pequeños, sino sería una locura, ya que tendríamos que conocer la factorización de 'n' y de phi(n).

Obtenemos 'd' de la siguiente forma:

d = e ^ phi(phi(n))- 1 (mod phi(n))
d = e ^ phi(phi((p).phi(q)))- 1 (mod (phi(p).phi(q))
d = e ^ phi((p-1).(q-1))- 1 (mod ((p-1).(q-1))

Código
  1. BigInteger p = 14188273085411836729, q = BigInteger.Parse("280615323801319888452039197798402115977");
  2. BigInteger n = BigInteger.Multiply(p,q);
  3. BigInteger phi = BigInteger.Multiply(p-1, q-1);
  4. BigInteger phiphi = BigInteger.Parse("646779039649951876929832079791621951934669155860480000000"); //Calculado en http://www.numberempire.com/numberfactorizer.php simplemente multiplica el totient de p-1 por el totient de q-1 y tienes el totient del totient
  5. BigInteger d = BigInteger.ModPow(65537, phiphi-1, phi);
  6. BigInteger r = BigInteger.ModPow(BigInteger.Multiply(65537, d), 1, phi);
  7. Console.WriteLine(r); //Comprobamos que la multiplicativa inversa se cumple e.d (mod phi(n)) = 1
  8. BigInteger c = BigInteger.ModPow(12345, 65537, n); //Calculamos el ciphertext 'c'
  9. BigInteger m = BigInteger.ModPow(c, d, n); //Recuperamos el mensaje original
  10. Console.WriteLine(m);

Saludos!