En muchos casos no se necesita generar las claves, porque ya existen, bien como bytes codificados en ficheros o como entradas en un keystore.
El defecto potencial es que nada garantiza la autenticidad de la clave pública que recibe el receptor, y el programa VerSig verifica correctamente la autenticidad de una firma sólo si la clave pública que se le suministra es propiamente auténtica.
Estos no son problemas en algunos casos, como cuando un sólo programa hace las dos cosas: la firma y la verificación.
Algunas veces los bytes codificados de la clave ya existen en ficheros para la pareja de claves para ser usados para la firma y verificación. Si este es el caso el programa GenSig puede importar los bytes codificados de la clave privada y convertirlos en un PrivateKey necesario para firmar, mediante el siguiente código, asumiendo que el nombre del fichero que contiene los bytes de la clave privada está en el string privkeyfile y que los bytes representan una clave DSA que ha sido codificada usando el estándard PKCS #8.FileInputStream keyfis = new FileInputStream(privkeyfile); byte[] encKey = new byte[keyfis.available()]; keyfis.read(encKey); keyfis.close(); PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(encKey); KeyFactory keyFactory = KeyFactory.getInstance("DSA"); PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);GenSig ya no necesita grabar los bytes de la clave pública en un fichero, ya están en un uno.En este caso el emisor envía al receptor:
- el fichero existente que contiene los bytes codificados de la clave pública (a menos que el receptor ya lo tenga) y
- el fichero de datos y el fichero de la firma exportado por GenSig.
El programa VerSig no se modifica, ya espera los bytes codificados de la clave pública en un fichero.
¿Pero qué pasa con el problema potencial de que un usuario malicioso intercepte los ficheros y los reemplace de forma que el cambio no pueda ser detectado? En algunos casos esto no es un problema, porque la gente ya ha intercambiado las claves públicas personalmente o mediante una tercera parte constratada que hace el intecambio cada-a-cara. Después de esto, se pueden hacer múltiples y consecutivos intercambios de ficheros remotamente (esto es, entre gente en diferentes localidades), y las claves públicas pueden usarse para verificar su autenticidad. Si un usuario malicioso intenta cambiar los datos o la firma, es detectado por VerSig.
Si no es posible el intercambio caro-a-cara, podemos probar otros métodos de incrementar la confianza del receptor. Por ejemplo, podríamos enviar nuestra clave pública de la forma más segura posible antes del intercambio de ficheros y firmas, quizas usando medios menos seguros.
En general, enviar los datos y la firma de forma separada de la clave pública reduce en gran medida la posibilidad de un ataque. A menos que se cambien los tres ficheros, y en cierta manera descrita en el siguiente párrafo, VerSig detectaría cualquier intento.
Si los tres ficheros (documento de datos, clave pública y firma) fueran interceptados por un usuario malicios, esa persona podría reemplazar el documento con otra cosa, firmarlo con una clave privada y reenviarlo en lugar del documento original, la nueva firma, y la clave pública correspondiente a la clave privada usada para generar la nueva firma. entonces, VerSig reportaría una verificación correcta y nosotros pensaríamos que el documento viene de su emisor original. Por eso debemos tomar los pasos necesarios para segurar que al menos la clave pública recibida está intacta (VerSig detecta cualquier modificación en los otros ficheros ), o podemos usar certificados para facilitar la autentificación de la clave pública, como se describe en la siguiente sección.
En criptografía es más común intercambiar certificados que contienen las claves públicas en vez de las propias claves.Un beneficio es que un certificado está firmado por una entidad (el emisor) para verificar que la clave pública encerrada es la clave pública real de otra entidad (el sujeto o propietario). Normalmente una autoridad de certificación (CA) verifica la identidad del sujeto y lo avala como el propietario de la clave pública firmando el certificado.
Otro beneficio del uso de certificados es que podemos chequear para segurarnos la validez del certificado recibido verificando su forma digital, usando la clave pública del emisor (firmante), que a su vez podría estar almacenada en otro certificado cuya firma puede ser verificada usando la clave pública del emisor del certificado, que a su vez puede estar almacenada en otro certificado, etc, hasta alcanzar una clave pública en la que realmente creamos.
Si no podemos establecer una cadena verdadera (quizás porque el certificado del emisor no está disponible para nosotros), se puede calcular la huella dactilar del certificado. Cada huella dactilar es un número relativamente corto y único que identifica relativamente el certificado. (Técnicamente es un valor de la información del certificado, usando un mensaje, también conocido como función picadillo de un camino). Podemos llamar al propietario del certificado y comparar las huellas dactilares del certificado que hemos recibido con los que nos envió. Si son iguales, los certificados con el mismo.
Sería más seguro para GenSig crear un certificado que contenga la clave pública para que VerSig luego importara el certificado y extrajera la clave pública. Sin embargo, el JDK no tiene API para certificados públicos que puedan permitirnos crear un certificado desde una clave pública, por eso el programa GenSig no puede crear un certificado para la clave pública generada. (Si que hay un API público para extraer una clave pública desde un certificado, creo).
Si queremos, podemos usar varias herramientas de seguridad, no APIs, para firmar documentos importantes y trabajar con certificados de un keystore, como se hizo en la lección Intercambiar Ficheros.
Alternativamente podemos usar el API para modificar nuestros programas para que trabajen con un clave privada ya existente y su correspondiente clave pública (en un certificado) desde nuestro keystore. Para empezar, modicamos el programa GenSig para extraer la clav eprivada desde el keystore en vez de generar las claves nuevas. Primero, asumamos lo siguiente:
Luego podemos extraer la clave privada del keystore mediante esto:
- El nombre del keystore está en el String ksName
- El tipo de keystore es "JKS", el tipo propietario creado por Sun Microsystems
- El password del keystore está en el array de caracteres spass
- El alias de la entrada del keystore que contiene la clave privada, y el certificado de la clave pública está en el String alias
- El password de la clave privada está en el array de caractereskpass
KeyStore ks = KeyStore.getInstance("JKS"); FileInputStream ksfis = new FileInputStream(ksName); BufferedInputStream ksbufin = new BufferedInputStream(ksfis); ks.load(ksbufin, spass); PrivateKey priv = (PrivateKey) ks.getKey(alias, kpass);Podemos extraer el certificado de la clave pública desde el keystore y grabar sus bytes codificados en un fichero llamado suecert, mediante esto:java.security.cert.Certificate cert = ks.getCertificate(alias); byte[] encodedCert = cert.getEncoded(); /* save the certificate in a file named "suecert" */ FileOutputStream certfos = new FileOutputStream("suecert"); certfos.write(encodedCert); certfos.close();Luego enviamos el fichero de datos, la firma y el certificado al receptor. El receptor verifica la autenticidad del certificado primero obteniendo la huella dactilar del certificado, mediante el comando keytool -printcert:keytool -printcert -file suecert Owner: CN=Susan Jones, OU=Purchasing, O=ABC, L=Cupertino, ST=CA, C=US Issuer: CN=Susan Jones, OU=Purchasing, O=ABC, L=Cupertino, ST=CA, C=US Serial number: 35aaed17 Valid from: Mon Jul 13 22:31:03 PDT 1998 until: Sun Oct 11 22:31:03 PDT 1998 Certificate fingerprints: MD5: 1E:B8:04:59:86:7A:78:6B:40:AC:64:89:2C:0F:DD:13 SHA1: 1C:79:BD:26:A1:34:C0:0A:30:63:11:6A:F2:B9:67:DF:E5:8D:7B:5ELuego el recepto verifica las huellas dactilares, quizás llamando al emisor y comparandolas con las huellas del certificado recibido o buscándolas en un repositorio público.El programa de verificación del receptor (un VerSig modificado) puede importar el certificado y extraerle la clave pública mediante esto, asumiento que el nombre del fichero del certificado (por ejemplo, suecert) está en el String certName.
FileInputStream certfis = new FileInputStream(certName); java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509"); java.security.cert.Certificate cert = cf.generateCertificate(certfis); PublicKey pub = cert.getPublicKey();
Supongamos que queremos mantener confidenciales los contenidos de los datos para la gente no pueda ver el contenido durante el tránsito (o en nuestra propia máquina o disco. Para hacer esto, deberíamos encriptar y almacenar y enviar sólo el resultado de la encriptación (referido como ciphertext). El recepto puede desencriptar el ciphertext para obtener una copia de los datos originales.APIs para la encriptación y desencriptación, junto con otras implementaciones de algoritmos por defecto, están liberadas de forma separada en el Java Cryptography Extension (JCE), y añade un paquete al JDK, en concordancia con las regulaciones de control de exportación de los U.S.