lunes, 2 de junio de 2008

Algoritmos de encriptación en JAVA

Trabajando en estos temas en programación JAVA he tenido la necesidad de encriptar datos que no podían guardarse planamente en ninguna base de datos, como por ejemplo, passwords.

He trabajado con SHA-1 (irreversible) y DES (reversible con clave).

SHA-1 (Secure Hash Algorithm - 1)

Web: http://es.wikipedia.org/wiki/SHA

Muy útil para funciones de login y guardar los passwords de los usuarios encriptados.

Estas funciones hash tienen la particularidad de que son de una sola vía: a partir de un texto puedes obtener el código hash, pero no a la inversa (no es posible obtener el texto a partir del código hash).
Además, es virtualmente imposible conseguir dos textos que generen el mismo código hash.
Otra peculiaridad de este sistema es que los códigos hash generados no son texto plano, sino un conjunto arbitrario de bits, eso sí, de longitud fija.
El sistema sería el siguiente:



  1. En la base de datos guardas no las contraseñas, sino sus códigos MD5 o SHA1 traducidos a hexadecimal.

  2. Cuando quieres comprobar un par nombre de usuario - contraseña, obtienes el código MD5 o SHA1 de la contraseña, lo pasas a hexadecimal y lo comparas con el que tienes almacenado para ese nombre de usuario.

  3. Si coincide, hasta la cocina: la contraseña es correcta.

  4. Si no coincide, aire.


La llamada se hará de esta manera:

String encriptado = "";

encriptado = SHA1.encriptarHexadecimal("SILVANO");

y retornará encriptado = "37b418aea1bafd89ab9cdca29f2b3b0ba64b73e3";

Ésta sería la clase Java de SHA-1:






DES (DATA ENCRYPTION STANDARD)

Web: http://en.wikipedia.org/wiki/Data_Encryption_Standard


Este algoritmo es reversible mediante una clave, tanto para encriptar como para descencriptar.
Será útil para datos económicos, los cuales el usuario puede verlos (desencriptado mediante programa) si tiene acceso pero en base de datos se guardan encriptados.

Mejoras: TRIPLE DES y AES (ADVANCED ENCRYPTION STANDARD)


La llamada sería la siguiente:

try {


// Create encrypter/decrypter class

String clave = "ricardo";

System.out.println("CLAVE: "+clave);

DES encrypter = new DES(clave);

String original = "SILVANO";

System.out.println("ORIGINAL: "+original);

// Encrypt

String encrypted = encrypter.encrypt(original);

System.out.println("ENCRIPTADO: "+encrypted);

// Decrypt

String decrypted = encrypter.decrypt(encrypted);

System.out.println("DESENCRIPTADO: "+decrypted);

} catch (Exception e) {



}


Ésta sería la clase Java de DES:


import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;

import javax.crypto.*;
import javax.crypto.spec.*;

import sun.misc.CEStreamExhausted;
import sun.misc.CharacterEncoder;
import sun.misc.HexDumpEncoder;

import java.io.*;

public class DES {

Cipher ecipher;
Cipher dcipher;

// 8-byte Salt
byte[] salt = {
(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
(byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03
};

// Iteration count
int iterationCount = 19;

DES(String passPhrase) {
try {
// Create the key
KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance(
"PBEWithMD5AndDES").generateSecret(keySpec);
ecipher = Cipher.getInstance(key.getAlgorithm());
dcipher = Cipher.getInstance(key.getAlgorithm());

// Prepare the parameter to the ciphers
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);

// Create the ciphers
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
} catch (java.security.InvalidAlgorithmParameterException e) {
} catch (java.security.spec.InvalidKeySpecException e) {
} catch (javax.crypto.NoSuchPaddingException e) {
} catch (java.security.NoSuchAlgorithmException e) {
} catch (java.security.InvalidKeyException e) {
}
}

public String encrypt(String str) {
try {
// Encode the string into bytes using utf-8
byte[] utf8 = str.getBytes("UTF8");

// Encrypt
byte[] enc = ecipher.doFinal(utf8);

// Encode bytes to base64 to get a string
return new sun.misc.BASE64Encoder().encode(enc);

} catch (javax.crypto.BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
} catch (java.io.IOException e) {
}
return null;
}

public String decrypt(String str) {
try {
// Decode base64 to get bytes
byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);

// Decrypt
byte[] utf8 = dcipher.doFinal(dec);

// Decode using utf-8
return new String(utf8, "UTF8");
} catch (javax.crypto.BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
} catch (java.io.IOException e) {
}
return null;
}


}

No hay comentarios: