Almacenamiento de contraseñas seguro, sincronizado y multiplataforma
Si utilizas varios equipos (quizá diferentes SO) y utilizas diversas y complejas contraseñas (recomendado), tendrás la necesidad de:
- Almacenar tus contraseñas de manera segura.
- Poder acceder a ellas desde cualquier equipo (multiplataforma) y mantenerlas sincronizadas.
- Idealmente, poder usar una contraseña sin tener que visualizarla (ver vídeo más adelante) – función auto-type
- Poder definir fechas de caducidad para renovar las contraseñas (y que tu gestor de contraseñas te las recuerde)
Después de mucho buscar he encontrado la solución usando estas dos herramientas: KeePass + DropBox
Visión general

- Se instala KeePass o KeePassX en cada máquina. Disponible para multiplataforma.
- Se instala DropBox en cada máquina. También disponible para varias plataformas.
- El archivo de contraseñas permanece siempre cifrado y sincronizado a través de DropBox
- El archivo permanece doblemente protegido: por un lado el cifrado seguro de KeePass. Por otro, la capa de con la que DropBox almacena sus datos.
- En caso de que al archivo de contraseñas pudiera quedar defectuoso, DropBox te permite ir a la versión anterior (mantiene un histórico de versiones)
Instalación
Puedes descargar KeePass aquí (para Windows) o también usar el gestor de paquetes o dpkg para Linux para obtener KeePassX, o descargarlo desde: http://www.keepassx.org/
Del sitio web de KeePassX:
“Originally KeePassX was called KeePass/L for Linux since it was a port of Windows password manager Keepass Password Safe. After KeePass/L became a cross platform application the name was not appropriate anymore and therefore, on 22 March 2006 it has been changed.”
La idea consiste en tener instalado KeePass y mantener el archivo KDB de contraseñas en tu DropBox. El archivo de contraseñas será sincronizado entre todos los equipos que tengas, y puede ser abierto por KeePass en Windows, o KeePassX en Linux o MacOs.
Nota: screenshots obtenidos de las páginas de KeePass y KeePassX
Seguridad
El archivo de contraseñas se protege mediante un cifrado considerado seguro (ver http://keepass.info/help/base/security.html). Incluso en memoria, los datos sensibles se mantienen cifrados mientras el gestor de contraseña los utiliza.
“In order to generate the 256-bit key for the block ciphers, the Secure Hash Algorithm SHA-256 is used. This algorithm compresses the user key provided by the user (consisting of password and/or key file) to a fixed-size key of 256 bits. This transformation is one-way, i.e. it is computationally infeasible to invert the hash function or find a second message that compresses to the same hash.
The recently discovered attack against SHA-1 [2] doesn’t affect the security of SHA-256. SHA-256 is still considered as being very secure [3].”
Función auto-type
Usando la función auto-type puedes introducir las credenciales sin tener que visualizar la contraseña. Siempre, los datos sensibles permanecen cifrados en memoria. Vídeo corto demostrativo:
¿Alguna sugerencia o comentario? ¿Como lo hacéis vosotros?
Ejemplo Backgroundworker en C#
Nota: Ejemplo completo de uso del control BackgroundWorker. El artículo inicial se creó en inglés y fue publicado aquí. En vista del éxito que ha tenido lo traduzco al castellano y lo republico también en este apartado.
Introducción
El control BackgroundWorker fue introducido en el .NET Framework 2.0 y permite realizar operaciones costosas o duraderas en un hilo diferente al del interfaz, de manera que la aplicación sigue respondiendo al usuario mientras este trabajo se procesa en segundo plano.
Usando este control, la gestión de hilos está encapsulada en el control de manera que el programador no tiene que lidiar con hilos (threads), invokes o delegados (delegates).
Ejemplo
Este sencillo ejemplo cubre prácticamente todas las posibilidades de este componente: soporte de cancelación, gestión de errores , información de progreso (y ejemplo de como pasar información en cada notificación de progreso)
Evento backgroundWorker1_DoWork
El evento backgroundWorker1_DoWork es desencadenado por el control cuando el método RunWorkerAsync() es invocado. Este método se ejecuta en un segundo hilo que crea el control BackgroundWorker. Al no ser el hilo principal del interfaz, no intentes acceder a ningún control aquí, o si lo haces utiliza para ello un delegado.
//[System.Diagnostics.DebuggerNonUserCodeAttribute()] (*)
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//no usaremos código try/catch aquí, a no ser que después hagamos un throw de la excepción capturada.
//es necesario dejar que el backgroundworker sea quien capture cualquier excepción producida.
//si se produce una excepción, el control la disponibilizará una vez haya finalizado su ejecución,
//y disparado el evento "backgroundWorker1_RunWorkerCompleted"
//the RunWorkerCompletedEventArgs object, method backgroundWorker1_RunWorkerCompleted
//try
//{
DateTime start = DateTime.Now;
e.Result = "";
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(50); //simulamos trabajo
//hemos completado un porcentaje del trabajo previsto, luego notificamos de ello.
backgroundWorker1.ReportProgress(i, DateTime.Now);
//descomenta este código para ver como esta excepción es gestionada por el
//control backgroundworker
//descomenta también el atributo indicado arriba para evitar que el depurador
//pare en la excepción, ya que queremos simular
//el comportamiento del control en tiempo de ejecución.
//if (i == 34)
// throw new Exception("something wrong here!!");
//en caso de que soporte cancelación y el control haya recibido la petición de cancelación,
//cancelamos el trabajo. Es la manera en la que realizamos una salida "limpia".
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
}
TimeSpan duration = DateTime.Now - start;
//aquí podríamos devolver información de utilidad, como el resultado de un cálculo,
//número de elementos afectados, etc.. de manera sencilla y segura
//al hilo principal
e.Result = "Duration: " + duration.TotalMilliseconds.ToString() + " ms.";
//}
//catch(Exception ex){
// MessageBox.Show("Don't use try catch here!");
//}
}
(*) Nota: El atributo [System.Diagnostics.DebuggerNonUserCodeAttribute()] es necesario para evitar que el depurador interrumpa el flujo de la ejecución en caso de que una excepción se produzca. De esta manera podemos trabajar en modo depuración con el mismo comportamiento que el control tendría en modo ejecución. Este comportamiento consistiría en capturar internamente la excepción (por eso no usaremos try/catch en el método) y devolvernos la misma junto con el resultado, en el método backgroundWorker1_RunWorkerCompleted
Evento backgroundWorker1_ProgressChanged
Este evento es lanzado en el hilo principal, por lo que aquí SI podemos acceder a controles del formulario de manera segura.
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage; //actualizamos la barra de progreso
DateTime time = Convert.ToDateTime(e.UserState); //obtenemos información adicional si procede
//en este ejemplo, logamos a un textbox
txtOutput.AppendText(time.ToLongTimeString());
txtOutput.AppendText(Environment.NewLine);
}
Evento backgroundWorker1_RunWorkerCompleted
Este método se ejecuta cuando la tarea ha sido finalizada. Una tarea se finaliza cuando:
- a) termina de manera normal
- b) termina con error
- c) es cancelada.
En el objeto de tipo RunWorkerCompletedEventArgs encontraremos información detallada del tipo de finalización, así como los datos que hemos podido pasar en la propiedad Result.
private void backgroundWorker1_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Cancelled) {
MessageBox.Show("The task has been cancelled");
}
else if (e.Error != null)
{
MessageBox.Show("Error. Details: " + (e.Error as Exception).ToString());
}
else {
MessageBox.Show("The task has been completed. Results: " + e.Result.ToString());
}
}
Enviado las órdenes de inicio y cancelación al control
Notificamos al control backgroundworker de que cancele el proceso.
private void btoCancel_Click(object sender, EventArgs e)
{
//este código no mata ni afecta al hilo en el que se está ejecutando el procesamiento.
//Sirve a efectos de notificación, que debe de ser
//gestionada de la manera que se indica arriba en el ejemplo
backgroundWorker1.CancelAsync();
}
Lanzamos el trabajo. En este momento, el control backgroundworker lanza un hilo en el que ejecuta la tarea asignada, a través del método backgroundWorker1_DoWork visto anteriormente.
private void btoStart_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
Trabajar con repositorio SVN sin servidor dedicado (usando DropBox)
Note: english version available here: Working with SVN and DropBox without a dedicated SVN server
En algunos foros se plantea el uso del servicio DropBox como sustituto del repositorio de código fuente – SVN en nuestro caso – (ventajas de DropBox: archivos sincronizados en múltiples equipos, múltiples colaboradores trabajando simultáneamente, DropBox te mantiene versiones de los archivos una vez modificados, etc…)
Si trabajas como freelance o en equipos muy pequeños, te propongo que mantengas el uso del repositorio SVN (con su capacidad de fusión, sincronización, comparación, histórico, etc), pero aprovechando la potencia de DropBox, para que no necesites tener un servidor SVN conectado las 24 horas por día.
Tu tienes un servidor SVN en cada equipo y DropBox los sincroniza como si fueran uno solo servidor permanentemente conectado.
Además, mantienes todo el histórico de cambios en el código fuente dependiendo de SVN (código fuente disponible, licencia abierta) y no de DropBox (no disponible, propietario, no dispones de los archivos versionados en si), y también tienes la opción de cuando quieras migrar a un servidor de SVN dedicado.
Procedimiento
El procedimiento es sencillo:
- Creas una cuenta de DropBox si no la tienes ya e instalas el software (si usas este enlace nos dan 250Mb extras a cada uno – nada más
) - Al no tener un único repositorio, necesitarás instalar el servidor SVN en cada equipo (tu portátil, el de escritorio, el Mac, el de Linux, en casa, en la oficina, etc).En todos ellos ubicas el repositorio dentro de la carpeta sincronizada que crea DropBox. En los pantallazos uso VisualSVN Server para Windows pero este tutorial es multiplataforma (tanto SVN como DropBox lo son)
- Importante, para unificar la ruta, vamos a crear una entrada en el archivo hosts de cada máquina que utilices para desarrollar, que apunte al propio equipo (es decir a 127.0.0.1) : ej:
127.0.0.1 svn.midominio.com #el nombre es lo de menos, invéntatelo.
De esta manera hacemos que el ROOT o raíz del repositorio se mantenga constante entre todas las máquinas.
Ya está, ahora ya puedes trabajar en cualquiera de tus equipos, realizar cambios, y subir los mismos al repositorio SVN local (a través del mapeo que has hecho en el archivo HOSTS).
DropBox se encargará de replicar el repositorio al resto de tus equipos de trabajo por lo que cuando entres en otro equipo y realices un update del SVN (local a ese equipo) estarás obteniendo las últimas modificaciones.
Virtualmente trabajarás como si tu repositorio SVN estuviese en un servidor de Internet!
Anexo
Servidor SVN para Windows:
Cliente SVN para Windows:
Sobre el fichero HOSTS:
- http://es.wikipedia.org/wiki/Archivo_hosts
- Notas: Recuerda abrirlo como administrador en Vista (notepad -> botón derecho -> abrir como administrador)






