martes, 14 de abril de 2015

Tutorial Bluetooth


Pese a que en la actualidad la tecnología Bluetooth no es muy usada frente a la capacidad que ofrece Internet, es importante saber cómo programar aplicaciones que la utilicen. En esta entrada se expone un breve tutorial con los pasos a realizar para que nuestra aplicación pueda usar Bluetooth. Se parte de la base de que el dispositivo bluetooth ya está vinculado con el dispositivo con el que quiere establecer la conexión.

  • Se instancia e inicializa la clase BluetoothAdapter para obtener el adaptador de Bluetooth con getDefaultAdapter().
  • Se obtienen los dispositivos vinculados con getBondedDevices(). 
  • Se establece el dispositivo de los dos va a actuar como servidor y el que va a actuar como cliente. 
  • El servidor ha de extender la clase Thread, crear un BluetoothServerSocket mediante listenUsingRfcommWithServiceRecord() y escuchar peticiones en el método run a través de bluetoothserversocket.accept(). 
  • El cliente ha de extender la clase Thread, crear un BluetoothSocket utilizando el BluetoothDevice que actúa como servidor y el UUID de la aplicación mediante el método createRfcommSocketToServiceRecord() y en el método run llamar a la clase connect().
  • Cuando el cliente se conecte al servidor, ambos dispondrán de un socket BluetoothSocket con el que manejar la conexión. Ya solo queda instanciar las clases InputStream y OutputStream.

En el siguiente enlace de Github se encuentra el respositorio con la aplicación de ejemplo y el tutorial más extenso en PDF: repositorio

Además dejo un enlace a una serie de tutoriales Bluetooth de Daniel García que me sirvieron para aprender cómo utilizar Bluetooth en Android: tutoriales Bluetooth

domingo, 12 de abril de 2015

Seguridad: Puntos de acceso Wi-Fi gratuitos

Hoy he podido encontrar una noticia, publicada por el periódico ABC, en la que se afirma que "Hasta una niña de 7 años puede robar tus datos". La noticia puede leerse aquí.


En la noticia comentan que lo fácil que es obtener información sensible de usuarios que se conectan a una red Wi-Fi gratuita como puede ser la de cualquier establecimiento o cualquier red a la que nuestro dispositivo tenga posibilidad de conectarse. Además al final de la noticia aparece cómo, efectivamente, una niña británica de 7 años fue capaz de robar información de los dispositivos que estaban a su alrededor. La pregunta es: ¿Cómo es posible esto? Existen varios factores:

1. Cuando nos conectamos a una red desconocida, ajena a la nuestra, cabe la posibilidad de que dicha red sea falsa. Un hacker es capaz de utilizar su dispositivo como pasarela a Internet, de modo que al conectarte a la red todo el tráfico que se está generando pase a través de su dispositivo. Esto es lo que en seguridad se conoce como un ataque Man in the middle. A partir de ese momento es capaz de obtener toda la información de la que dispone y más, ya que no sólo puede ver dónde estás conectado o la información de tu móvil, sino que puede obtener contraseñas y números bancarios con los que puede llevar a cabo robos de información altamente sensible.

2. Dado el caso de que no sea una red ficticia sino que, efectivamente, sea una red real del establecimiento en el que nos encontremos (por ejemplo, una cafetería), no existen los mecanismos de seguridad adecuados que protejan nuestra información. Cuando desde la red de tu casa te conectas a Internet se establecen varios mecanismos de seguridad como el uso de direcciones IP privadas y cortafuegos en los routers de salida de tu red y en puntos intermedios de la red de tu operador. Sin embargo, cuando te conectas a la red de un local no existen tales mecanismos.

Los firewall en los routers solo protegen la red del exterior

El objetivo de las direcciones privadas, aparte de ahorrar direcciones IP públicas, es la de impedir que un usuario fuera de tu red sepa tu dirección IP pública y pueda realizar un ataque directo. Al encontrarte en la misma red con un montón de usuarios desconocidos, dichos usuarios pueden acceder fácilmente a la dirección IP privada dentro de tu dispositivo y, por ende, atacarlo. Además el uso de los cortafuegos a la salida de la red no tiene ninguna validez para dispositivos dentro de la misma, ya que sólo gestiona la información que viene de Internet o va hacia Internet.

Por lo tanto para evitar disgustos y posibles robos de información, es importante seguir los siguientes consejos:

- Estar plenamente seguro de que el punto de acceso Wi-Fi es de confianza y no es falso. NUNCA se ha de establecer una conexión con una red que no necesite contraseña para acceder a ella a menos que se esté seguro de que es de confianza.

- Evitar en la medida de lo posible acceder a páginas web en la que se haga uso de información privada, como pueden ser webs bancarias o redes sociales. Pese a que la información va encriptada desde que sale de nuestro dispositivo, es mucho más "fácil" para un hacker poder desencriptarla si tiene acceso directo a través de un ataque al ordenador o móvil del que procede dicha información.

Para finalizar, aunque haya que tener cuidado con los puntos de acceso Wi-Fi gratuitos de los establecimientos, afortunada (o desafortunadamente) no mucha gente tiene conocimientos acerca de seguridad y por lo tanto acerca de cómo comprometerla.

sábado, 4 de abril de 2015

Cifrado AES en Java

Vamos pues a ver hoy cómo cifrar un mensaje en JAVA. En este caso se va utilizar el algoritmo de cifrado AES, pero existen multitud de estándares para el cifrado de la información. El cifrado AES es un esquema de cifrado por bloques en el que se utiliza una clave de 128,192 o 256 bits. Para saber más acerca de este tipo de cifrado: http://es.wikipedia.org/wiki/Advanced_Encryption_Standard y http://www.codeplanet.eu/files/flash/Rijndael_Animation_v4_eng.swf

Lo primero que se necesita para llevar a cabo el cifrado es una clave. En este caso la clave es de 128 bits, pero podría ser de 192 o 256 bits. Para generar la clave se hace uso de la clase keyGenerator.

private Cipher cifrado;    // clase Cypher para cifrado/descifrado
private byte[] iv;             // Vector de inicialización
private Cipher descifrado;  
private ByteArrayOutputStream outputStream;    //flujo de salida de datos encriptados/desencriptados

En el constructor de la clase:

KeyGenerator kgen;              //clase Keygenerator para generar la clave

kgen = KeyGenerator.getInstance("AES");      //indicamos que se quiere utilizar AES
kgen.init(128);                                                  //se indica que se quieren utilizar 128 bits
SecretKey aesKey = kgen.generateKey();       //se genera la clave

Con esto ya se tiene creada nuestra clave, "aesKey". El siguiente paso es crear una clase Cipher para el cifrado y descifrado. Para el primer caso:

cifrado = Cipher.getInstance("AES/CBC/PKCS5Padding");
cifrado.init(Cipher.ENCRYPT_MODE, aesKey);

La primera línea indica que se quiere utilizar un cifrado AES en modo de cifrado de bloque (CBC) y puesto que es un cifrado de bloque, que se requiere de "padding" (relleno). La segunda linea indica que se quiere utilizar el modo de encriptación (cifrado) y se quiere utilizar la clave generada anteriormente.

Para descifrar podríamos utilizar la misma clase Cipher indicandole ahora que se quiere el modo descifrado, pero en este ejemplo se crea otra clase para verlo un poco más claro:

descifrado = Cipher.getInstance("AES/CBC/PKCS5Padding");
iv = cifrado.getIV();
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
descifrado.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);

La diferencia ahora es que se utiliza un vector de bytes para el descifrado. Este vector iv es muy importante por motivos de seguridad, y su utilidad radica en que dada la misma clave y diferentes vectores de inicialización, el resultado es diferente. Más información aquí: http://es.wikipedia.org/wiki/Vector_de_inicializaci%C3%B3n

Ahora que ya se tienen inicializadas las clases Cipher para cifrar y descifrar, se crean dos métodos para el cifrado y descifrado:

public byte[] cifrarMensaje(String mensaje){
     
        String mensajeCifrado = null;
        byte[] BytesEncriptados = null;
     
        try {
            outputStream = new ByteArrayOutputStream();
            try (CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cifrado)) {
                cipherOutputStream.write(mensaje.getBytes());
                cipherOutputStream.flush();
            }
            BytesEncriptados = outputStream.toByteArray();
         
        } catch (IOException ex) {
            Logger.getLogger(ejemploCifrado.class.getName()).log(Level.SEVERE, null, ex);
        }
     
        return BytesEncriptados;
     
    }
 
    public String descifrarMensaje(byte[] mensaje){
     
        outputStream = new ByteArrayOutputStream();
        ByteArrayInputStream inStream = new ByteArrayInputStream(mensaje);
        CipherInputStream cipherInputStream = new CipherInputStream(inStream, descifrado);
        byte[] buf = new byte[1024];
        int bytesRead;
        try {
            while ((bytesRead = cipherInputStream.read(buf)) >= 0) {
                outputStream.write(buf, 0, bytesRead);
            }
        } catch (IOException ex) {
            Logger.getLogger(ejemploCifrado.class.getName()).log(Level.SEVERE, null, ex);
        }
     
        return new String(outputStream.toByteArray());
     
    }

La primera clase es la encargada del cifrado. Recibe el String a cifrar y devuelve un vector de bytes con el mensaje cifrado. Lo que se hace fundamentalmente es generar un ByteArrayInputStream  que será el encargado de recibir los bytes encriptados y abrir un flujo de cifrado de bytes CipherOutputStream que se encargue de convertir el mensaje a bytes, cifrarlo y pasarselo al ByteArrayInputStream. Este último convierte el flujo de bytes obtenido a un vector de bytes.

La segunda hace el camino inverso: recibe un vector de bytes cifrado y devuelve el string descifrado.

IMPORTANTE: cada algoritmo de cifrado tiene sus propias características, por lo que si se cambia alguno de los parámetros es posible que no funcione. Es importante a la hora de añadir un tipo de cifrado especifico leer primero acerca de cómo funciona.

El código completo se encuentra aquí: https://github.com/VicenteCantonPaterna/CifradoSimple

Está desarrollado en netbeans y por tanto habría que crear un proyecto para Android, pero se puede comprobar su funcionamiento fácilmente. El código no lo he implementado yo sino que estuve intentando montar este minitutorial y en una página encontré uno que no me daba demasiados errores:

http://stackoverflow.com/questions/15554296/simple-java-aes-encrypt-decrypt-example

En realidad lo único que hice fue comentarlo un poco para que se pudiera entender cómo funciona (más o menos).

Espero que os sirva de algo!