toy OpenPGP cifrado con claves generadas manualmente

2

He estado jugando con el cifrado OpenPGP por un tiempo. Estos son los pasos que he seguido:

  • Genere un par de claves pública / privada sin cifrar en mi anillo de claves con gpg --gen-key .

  • Volcar las claves públicas y privadas en archivos con gpg --export-secret-key -a > private.key y gpg --export -a > public.key .

  • Inspeccione las claves con pgpdump -i public.key y pgpdump -i private.key .

  • Use Mathematica para verificar que p q == n , PowerMod[e, -1, LCM[(p - 1), (q - 1)]] == d y PowerMod[p, -1, q] == u .

  • Cifre un archivo de texto plano plain.txt con gpg -e -r <my email> -a -o crypt.gpg plain.txt .

  • Descifre el archivo de texto sin formato con gpg -d crypt.gpg .

Todo esto funciona bien. Sin embargo, me gustaría poder intentar cifrar / descifrar con las teclas que yo mismo genero : ¿es esto posible? Específicamente, me gustaría saber:

  • ¿Existe alguna herramienta que pueda usar para generar un par de llaves RSA a partir de un determinado p , q y e ?

  • Si no, y necesito implementar RFC 4880 , ¿qué paquetes de OpenPGP debo incluir? ¿GPG requiere que incluya un ID de usuario, firma y paquetes de subclave, o puedo salirme con solo una clave pública o un paquete de clave secreta en cada archivo?

    • Relacionado: hace la línea, "La suma de verificación [...] PUEDE aparecer en la primera línea después de los datos codificados en base64 "¿significa que el CRC base64 es opcional?
  • ¿Puedo hacer que GPG encripte y descifre usando estas claves sin agregándolas a mi llavero (ya que, al ser caseras, probablemente no sean seguras) ?

  • Finalmente, GPG no me permitirá generar claves de menos de 1024 bits. Si trato de cifrar / descifrar usando una clave de 128 bits generada de forma personalizada, ¿GPG lo permitirá? ¿Qué pasa con la clave de 12 bits p = 53, q = 61, e = 17 de ejemplo trabajado de Wikipedia ?

pregunta 2012rcampion 18.05.2015 - 21:49
fuente

1 respuesta

2

Miraste RSAKeyPairGenerator ( doc. ) ( ¿Fuente ) de BouncyCastle ? Genera un par de claves RSA y lo codifica. Apuesto a que puedes crear un objeto de par de llaves, llenarlo con tus valores y llamar a la función de codificación para obtener un archivo que acepte gpg.

EDIT :

He utilizado openssl para generar un par de llaves RSA y exportar los valores de sus componentes:

openssl genrsa -out rsa1024.pem 1024
openssl rsa -noout -text -in rsa1024.pem

He eliminado los separadores de bytes de dos puntos y las nuevas líneas de los valores de big int y he rellenado el exponente para que sea un número par de nibbles en hexadecimal.

Si aplica el siguiente parche a este archivo:

--- bcpg-jdk15on-152/org/bouncycastle/openpgp/examples/RSAKeyPairGenerator.java 2015-03-01 12:03:48.000000000 +0200
+++ src/foo/RSAKeyPairGenerator.java    2015-05-19 23:07:00.754583435 +0300
@@ -1,11 +1,13 @@
-package org.bouncycastle.openpgp.examples;
+package foo;

 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+import java.math.BigInteger;
 import java.security.InvalidKeyException;
 import java.security.KeyPair;
-import java.security.KeyPairGenerator;
+//import java.security.KeyPairGenerator;
 import java.security.NoSuchProviderException;
 import java.security.Security;
 import java.security.SignatureException;
@@ -13,6 +15,10 @@

 import org.bouncycastle.bcpg.ArmoredOutputStream;
 import org.bouncycastle.bcpg.HashAlgorithmTags;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateCrtKey;
+import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.openpgp.PGPEncryptedData;
 import org.bouncycastle.openpgp.PGPException;
@@ -76,11 +82,34 @@
     {
         Security.addProvider(new BouncyCastleProvider());

-        KeyPairGenerator    kpg = KeyPairGenerator.getInstance("RSA", "BC");
+        //KeyPairGenerator    kpg = KeyPairGenerator.getInstance("RSA", "BC");

-        kpg.initialize(1024);
+        //kpg.initialize(1024);

-        KeyPair                    kp = kpg.generateKeyPair();
+        //KeyPair                    kp = kpg.generateKeyPair();
+
+        BigInteger modulus = new BigInteger("00f4035469c2adf91d69052f94a8d466cae6ea485ecfd0dc6b1d408e8ef36ef2a60d907234c4e9e8e1261e42008a41140134fc62840338433ab5948b96ceb91b65b0aacf8b54deca21a90386ebe17df16ebd1bef137ba8a43e9e2671ecd0bc5cd052321d50e61eac532cf718309f76760b9e68690897d76a5f9955541f3bd87a89", 16);
+        BigInteger publicExponent = new BigInteger("010001", 16);
+        BigInteger privateExponent = new BigInteger("00abfc6cd2de54a0f109c48df4c9ca6b6937b889a9c9effc6bc3026d78743c0eeadb44a43a6d5030c40089f31b4e56f032a995fa19f1eb05f7ab6437bee395b4a867af07b71b8515728b44fed0f5c85367e182a00a8df3df3098b82e74f224b294c90e261869c81fb9b89824bec026b7189bad0c11d4366636e2d357ca06e591c1", 16);
+        BigInteger p = new BigInteger("00fdd4b067e9361abe40231470f8249e68d64aeade1828dcd8b60cb33942df55bb6806fa81784b5fc24f73d8313baac2c0150307e56df621c77cc650b2b6996193", 16);
+        BigInteger q = new BigInteger("00f619297aa83e72f5a0c9b0df87c1bb0927c17d70cf99c6a9f6c58ddbb848d40abdd0c853baf7de55ac8dfe84ba38d12e86703e4b82273066c252369a5f3534f3", 16);
+        BigInteger dP = new BigInteger("4dbd9e69b4db85454f8f6eeb4a94ac8f9f5242acd2e970fa4e87853cbc667a737360efc847778e548cd1061dce1076a52dca47d8d4dcd56baba37183cab91f51", 16);
+        BigInteger dQ = new BigInteger("64232af0a103002e1865d955ab5cd6294c86fbeeea5a6d2efd9db7325f932accd01de355c6af5345d337d807d3ea889b80d2ad56763852068e2d7bd066cb34a7", 16);
+        BigInteger qInv = new BigInteger("00c9cbb6242b3e748d557e12cbacaa4b3e5a7fd0573fcc31b77268a492e270055628a02a46ff4cefbdff28aaea289faca9826d8e22cf5b0f4de2e15bdd4b3d3d14", 16);
+
+        RSAKeyParameters pubkey_params = new RSAKeyParameters(false, modulus, publicExponent);
+        RSAPrivateCrtKeyParameters privkey_params = new RSAPrivateCrtKeyParameters(
+               modulus, publicExponent, privateExponent, p, q, dP, dQ, qInv);
+
+        Constructor<BCRSAPublicKey> pubkeyctor = BCRSAPublicKey.class.getDeclaredConstructor(RSAKeyParameters.class);
+        pubkeyctor.setAccessible(true);
+        BCRSAPublicKey pubkey = pubkeyctor.newInstance(pubkey_params);
+       
+        Constructor<BCRSAPrivateCrtKey> privkeyctor = BCRSAPrivateCrtKey.class.getDeclaredConstructor(RSAPrivateCrtKeyParameters.class);
+        privkeyctor.setAccessible(true);
+        BCRSAPrivateCrtKey privkey = privkeyctor.newInstance(privkey_params);
+
+        KeyPair kp = new KeyPair(pubkey, privkey);

         if (args.length < 2)
         {

Obtendrá un programa que cuando se ejecuta con argumentos "-a contraseña foo" produce archivos pub.asc y secret.asc que son un par de llaves pgp.

EDIT 2 :

$ pgpdump secret.asc 
Old: Secret Key Packet(tag 5)(510 bytes)
    Ver 4 - new
    Public key creation time - Tue May 19 22:56:20 IDT 2015
    Pub alg - RSA Encrypt or Sign(pub 1)
    RSA n(1024 bits) - ...
    RSA e(17 bits) - ...
    Sym alg - CAST5(sym 3)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA1(hash 2)
        Salt - 3b b9 cf f9 02 cf 90 9e 
        Count - 65536(coded count 96)
    IV - d8 ac aa 96 61 7a 03 34 
    Encrypted RSA d
    Encrypted RSA p
    Encrypted RSA q
    Encrypted RSA u
    Encrypted SHA1 hash
Old: User ID Packet(tag 13)(2 bytes)
    User ID - id
Old: Signature Packet(tag 2)(156 bytes)
    Ver 4 - new
    Sig type - Generic certification of a User ID and Public Key packet(0x10).
    Pub alg - RSA Encrypt or Sign(pub 1)
    Hash alg - SHA1(hash 2)
    Hashed Sub: signature creation time(sub 2)(4 bytes)
        Time - Tue May 19 22:56:20 IDT 2015
    Sub: issuer key ID(sub 16)(8 bytes)
        Key ID - 0xB01AC717560C7F68
    Hash left 2 bytes - ee a9 
    RSA m^d mod n(1024 bits) - ...
        -> PKCS-1
    
respondido por el Z.T. 19.05.2015 - 00:34
fuente

Lea otras preguntas en las etiquetas