sintaxis que programar programacion libro lenguaje ejemplos cómo codigos java encryption passphrase

programar - que es java



Cifrado de frase de paso de Java (7)

Use RFC2898 para generar claves a partir de contraseñas. Esto no está incluido en JRE o JCE, hasta donde yo sé, pero está incluido en servidores J2EE como JBoss , Oracle y WebSphere . También se incluye en .NET Base Class Library ( Rfc2898DeriveBytes ).

Hay algunas implementaciones de LGPL en Java, pero en un vistazo rápido, esta parece un poco más complicada. También hay una buena versión de JavaScript . (Produje una versión modificada de eso y lo empaqué como un componente de Windows Script)

Al carecer de una buena implementación con una licencia adecuada, preparé un código de Mattias Gartner. Este es el código en su totalidad. Corto, simple, fácil de entender. Está licenciado bajo la Licencia Pública MS .

// PBKDF2.java // ------------------------------------------------------------------ // // RFC2898 PBKDF2 in Java. The RFC2898 defines a standard algorithm for // deriving key bytes from a text password. This is sometimes // abbreviated "PBKDF2", for Password-based key derivation function #2. // // There''s no RFC2898-compliant PBKDF2 function in the JRE, as far as I // know, but it is available in many J2EE runtimes, including those from // JBoss, IBM, and Oracle. // // It''s fairly simple to implement, so here it is. // // Created Sun Aug 09 01:06:57 2009 // // last saved: // Time-stamp: <2009-August-09 02:19:50> // ------------------------------------------------------------------ // // code thanks to Matthias Gartner // // ------------------------------------------------------------------ package cheeso.examples; import java.security.NoSuchAlgorithmException; import java.security.InvalidKeyException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public class PBKDF2 { public static byte[] deriveKey( byte[] password, byte[] salt, int iterationCount, int dkLen ) throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException { SecretKeySpec keyspec = new SecretKeySpec( password, "HmacSHA1" ); Mac prf = Mac.getInstance( "HmacSHA1" ); prf.init( keyspec ); // Note: hLen, dkLen, l, r, T, F, etc. are horrible names for // variables and functions in this day and age, but they // reflect the terse symbols used in RFC 2898 to describe // the PBKDF2 algorithm, which improves validation of the // code vs. the RFC. // // dklen is expressed in bytes. (16 for a 128-bit key) int hLen = prf.getMacLength(); // 20 for SHA1 int l = Math.max( dkLen, hLen); // 1 for 128bit (16-byte) keys int r = dkLen - (l-1)*hLen; // 16 for 128bit (16-byte) keys byte T[] = new byte[l * hLen]; int ti_offset = 0; for (int i = 1; i <= l; i++) { F( T, ti_offset, prf, salt, iterationCount, i ); ti_offset += hLen; } if (r < hLen) { // Incomplete last block byte DK[] = new byte[dkLen]; System.arraycopy(T, 0, DK, 0, dkLen); return DK; } return T; } private static void F( byte[] dest, int offset, Mac prf, byte[] S, int c, int blockIndex ) { final int hLen = prf.getMacLength(); byte U_r[] = new byte[ hLen ]; // U0 = S || INT (i); byte U_i[] = new byte[S.length + 4]; System.arraycopy( S, 0, U_i, 0, S.length ); INT( U_i, S.length, blockIndex ); for( int i = 0; i < c; i++ ) { U_i = prf.doFinal( U_i ); xor( U_r, U_i ); } System.arraycopy( U_r, 0, dest, offset, hLen ); } private static void xor( byte[] dest, byte[] src ) { for( int i = 0; i < dest.length; i++ ) { dest[i] ^= src[i]; } } private static void INT( byte[] dest, int offset, int i ) { dest[offset + 0] = (byte) (i / (256 * 256 * 256)); dest[offset + 1] = (byte) (i / (256 * 256)); dest[offset + 2] = (byte) (i / (256)); dest[offset + 3] = (byte) (i); } // ctor private PBKDF2 () {} }

Estoy tratando de aprender cómo hacer encriptación basada en frase de contraseña con Java. Estoy encontrando varios ejemplos en línea, pero ninguno (todavía) en Stack Overflow. Los ejemplos son un poco ligeros en la explicación para mí, particularmente en lo que respecta a la selección del algoritmo. Parece que hay muchas cadenas que pasan para decir qué algoritmos usar, pero poca documentación sobre de dónde vienen las cadenas y qué significan. Y también parece que los diferentes algoritmos pueden requerir diferentes implementaciones de la clase KeySpec, por lo que no estoy seguro de qué algoritmos pueden usar la clase PBEKeySpec que estoy viendo. Además, todos los ejemplos parecen un poco desactualizados, muchos requieren que obtenga un paquete de criptografía anterior que solía no ser parte del JDK, o incluso una implementación de terceros.

¿Puede alguien proporcionar una introducción directa a lo que tengo que hacer para implementar cifrar (datos de cadena, frase de contraseña de cadena) y descifrar (datos de byte [], frase de contraseña de cadena)?


Puede usar un algoritmo hash (varias veces si es necesario) para pasar de la frase de contraseña a algunos datos brutos que puede usar como clave (+ un vector de inicialización si el algoritmo lo llama).

Luego puede usar esa clave con cualquier algoritmo simétrico, como 3DES-CBC o AES-CBC (DES se considera obsoleto en estos días).

Dependiendo de la JCE que tenga disponible, puede tener diferentes algoritmos a su disposición, pero AES es probablemente lo que desea. Sin embargo, la elección del algoritmo y la forma exacta de usarlo es un tema religioso, por lo que no es aconsejable que intente rodar el suyo propio o incluso que intente construir un esquema de cifrado propio con algoritmos estándar. Es casi seguro que te equivocarás si no lo has estudiado, y tal vez incluso si lo has hecho.

Si la seguridad es tan importante para usted que está considerando el cifrado, entonces debería considerar también consultar un libro de ingeniería de seguridad como Bruce Schneier o Ingeniería de seguridad por Ross Anderson: hay muchas trampas en la implementación. Por ejemplo, usar una frase de contraseña como clave no es para nada una gran idea, ya que básicamente reduce el tamaño de tu clave.

También puede ver los diseños que otras personas han hecho, hay muchos en el IETF, por ejemplo: http://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha1-00


Necesita una biblioteca de cifrado, que le indicará cómo configurarla.
Me gustan las cosas de bouncycastle.org. Puede encontrar su cómo hacerlo aquí. El DES al que se hace referencia en el ejemplo 5.1, es uno de los encriptadores que ofrecen. Lo que significa la cadena real dependerá del proveedor. Esencialmente cargas la biblioteca.

Security.addProvider(new BouncyCastleProvider());

Y luego solo use las interfaces de JCE para hacer lo que quiera:

keyGen = KeyGenerator.getInstance("DES", "BC");

Java maneja el enlace de la biblioteca y las interfaces para usted, no tiene que hacer eso. Estaría más que feliz de explicar más, si tienes alguna pregunta. Lamentablemente, en este momento estoy sufriendo de la enfermedad "No puedo recordar cómo lo aprendí", así que no dude en preguntar.


Seré cauteloso al dar o recibir consejos relacionados con la seguridad de un foro ... los detalles son bastante intrincados y, a menudo, se vuelven obsoletos rápidamente.

Habiendo dicho eso, creo que la Guía de referencia de Sun Java Cryptography Architecture (JCA) es un buen punto de partida. Consulte el ejemplo del código adjunto que ilustra el cifrado basado en contraseña (PBE).

Por cierto, el JRE estándar ofrece solo algunas opciones listas para usar para PBE ("PBEWithMD5AndDES" es uno de ellos). Para obtener más opciones, necesitará el "paquete de cifrado fuerte" o un proveedor de terceros como Bouncy Castle . Otra alternativa sería implementar su propio PBE utilizando los algoritmos de cifrado y cifrado proporcionados en el JRE. Puede implementar PBE con SHA-256 y AES-128 de esta manera ( métodos de cifrado / descifrado de muestra ).

En resumen, el método de cifrado para PBE puede implicar los siguientes pasos:

  1. Obtenga una contraseña y un texto claro del usuario y conviértalos en matrices de bytes.
  2. Genera una sal aleatoria segura.
  3. Agregue la sal a la contraseña y calcule su hash criptográfico. Repite esto muchas veces
  4. Encripte el texto sin formato usando el hash resultante como el vector de inicialización y / o la clave secreta.
  5. Guarde la sal y el texto cifrado resultante.

Si no necesita descifrar la frase de contraseña, sino solo generar una clave de cifrado basada en una contraseña / frase de contraseña, puede implementar el estándar PKCS # 5 , utilizando las clases de cifrado JCE y MessageDigest.


En la respuesta muy útil de Cheeso anterior, hay un error de mal funcionamiento.

La línea

int l = Math.max( dkLen, hLen)

no debe calcular el máximo, pero el techo de la división, por lo

int l = ((dkLen - 1) / hLen) + 1; // >= ceil(dkLen / hLen), == for dkLen =>1

Esto acelerará el cálculo en un factor de 20 para claves de 16 bytes.


Convierta su cadena en una matriz de bytes durante el cifrado. Convierte de nuevo a una cadena después del descifrado.

/** * Creates a cipher for encryption or decryption. * * @param algorithm PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES". * @param mode Encyrption or decyrption. * @param password Password * @param salt Salt usable with algorithm. * @param count Iterations. * @return Ready initialized cipher. * @throws GeneralSecurityException Error creating the cipher. */ private static Cipher createCipher(final String algorithm, final int mode, final char[] password, final byte[] salt, final int count) throws GeneralSecurityException { final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm); final PBEKeySpec keySpec = new PBEKeySpec(password); final SecretKey key = keyFactory.generateSecret(keySpec); final Cipher cipher = Cipher.getInstance(algorithm); final PBEParameterSpec params = new PBEParameterSpec(salt, count); cipher.init(mode, key, params); return cipher; } /** * Encrypts some data based on a password. * @param algorithm PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES" * @param data Data to encrypt * @param password Password * @param salt Salt usable with algorithm * @param count Iterations. * @return Encrypted data. */ public static byte[] encryptPasswordBased(final String algorithm, final byte[] data, final char[] password, final byte[] salt, final int count) { Validate.notNull(algorithm); Validate.notNull(data); Validate.notNull(password); Validate.notNull(salt); try { final Cipher cipher = createCipher(algorithm, Cipher.ENCRYPT_MODE, password, salt, count); return cipher.doFinal(data); } catch (final Exception ex) { throw new RuntimeException("Error encrypting the password!", ex); } } /** * Decrypts some data based on a password. * @param algorithm PBE algorithm like "PBEWithMD5AndDES" or "PBEWithMD5AndTripleDES" * @param encryptedData Data to decrypt * @param password Password * @param salt Salt usable with algorithm * @param count Iterations. * @return Encrypted data. */ public static byte[] decryptPasswordBased(final String algorithm, final byte[] encryptedData, final char[] password, final byte[] salt, final int count) { Validate.notNull(algorithm); Validate.notNull(encryptedData); Validate.notNull(password); Validate.notNull(salt); try { final Cipher cipher = createCipher(algorithm, Cipher.DECRYPT_MODE, password, salt, count); return cipher.doFinal(encryptedData); } catch (final Exception ex) { throw new RuntimeException("Error decrypting the password!", ex); } }