<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2spanishfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>4 bits blog</title>
	
	<link>http://blog.4bits.es</link>
	<description>Ahora en 16 colores</description>
	<lastBuildDate>Wed, 10 Mar 2010 11:58:51 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/4BitsBlog" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="4bitsblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://add.my.yahoo.com/content?lg=es&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2F4BitsBlog" src="http://eur.i1.yimg.com/eur.yimg.com/i/es/my/addto1.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2F4BitsBlog" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bloglines.com/sub/http://feeds.feedburner.com/4BitsBlog" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2F4BitsBlog" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2F4BitsBlog" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><item>
		<title>Detectar fugas de memoria en Visual Studio</title>
		<link>http://blog.4bits.es/detectar-fugas-de-memoria-en-visual-studio/</link>
		<comments>http://blog.4bits.es/detectar-fugas-de-memoria-en-visual-studio/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 11:58:51 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=480</guid>
		<description><![CDATA[Para los que programen en C con Visual Studio y sientan añoranza de valgrind, aquí están los pasos sobre cómo detectar fugas de memoria (memory leaks) en Visual Studio:

Añadir la macro _CRTDBG_MAP_ALLOC del preprocesador, ya sea definiéndola en algún archivo del proyecto o en las opciones de compilación del proyecto.
Incluir en el siguiente orden stdlib.h [...]]]></description>
			<content:encoded><![CDATA[<p>Para los que programen en C con Visual Studio y sientan añoranza de <a href="http://valgrind.org/">valgrind</a>, aquí están los pasos sobre <strong>cómo detectar fugas de memoria (<em>memory leaks</em>) en Visual Studio</strong>:</p>
<ul>
<li>Añadir la macro <code>_CRTDBG_MAP_ALLOC</code> del preprocesador, ya sea definiéndola en algún archivo del proyecto o en las opciones de compilación del proyecto.</li>
<li>Incluir en el siguiente orden <code>stdlib.h</code> y <code>crtdbg.h</code> en los archivos dónde se busquen las fugas de memoria. El archivo <code>crtdgb.h</code> sustituye las funciones <code>malloc</code> y <code>free</code> por unas propias que registran la memoria reservada y liberada.</li>
<li>Añadir la función <code>_CrtDumpMemoryLeaks ()</code> al final del programa en el que se buscan las fugas de memoria. Esta función muestra por la salida de depuración las fugas de memoria detectadas.</li>
</ul>
<p>Todo <strong>esto sólo funcionará cuando el proyecto se compile con la macro <code>_DEBUG</code> definida</strong>, es decir, en lo que debería ser para todos la versión de depuración del programa.</p>
<p>La macro <code>_CRTDBG_MAP_ALLOC</code> sirve para que la función <code>_CrtDumpMemoryLeaks ()</code> muestre información sobre el archivo y la línea en la que se produjo la fuga de memoria.</p>
<p>Un pequeño ejemplo de cómo quedaría todo:</p>
<pre class="brush:c">#define _CRTDBG_MAP_ALLOC
#include &lt;stdlib.h&gt;
#include &lt;crtdbg.h&gt;

int
main (int argc, char *argv[])
{
    /* Código del programa */

    _CrtDumpMemoryLeaks ();

    return 0;
}</pre>
<p>Si este programa tuviera alguna fuga de memoria, al compilarlo en modo depuración y ejecutar el depurador de Visual Studio, se obtendría en la salida de éste un listado con las fugas de memoria del programa.</p>
<p>Para más información, leed el artículo <a href="http://msdn.microsoft.com/en-us/library/e5ewb1h3(v=VS.80).aspx">Enabling Memory Leak Detection</a> de la MSDN.</p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/cEPNhJKYxd0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/detectar-fugas-de-memoria-en-visual-studio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>El extraño bug del Calendar</title>
		<link>http://blog.4bits.es/el-extrano-bug-del-calendar/</link>
		<comments>http://blog.4bits.es/el-extrano-bug-del-calendar/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 19:15:05 +0000</pubDate>
		<dc:creator>Lek</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=466</guid>
		<description><![CDATA[Cuando empezaba a programar con C y C++ recuerdo los quebraderos de cabeza para comprobar que los valores &#8220;entraban&#8221; dentro de las variables y evitar desbordamientos problemáticos. Java solucionó esto haciendo que, si el valor se pasaba del rango de la variable, se reiniciaba el contador. Es decir, que si queremos poner el valor 212 [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando empezaba a programar con C y C++ recuerdo los quebraderos de cabeza para comprobar que los valores &#8220;entraban&#8221; dentro de las variables y evitar desbordamientos problemáticos. Java solucionó esto haciendo que, si el valor se pasaba del rango de la variable, se reiniciaba el contador. Es decir, que si queremos poner el valor 212 a un fichero byte (-128 a 127), Java nos muestra en realidad -44.</p>
<p>Esto, que en principio puede parecer un gran avance porque evita problemas de seguridad en los programas (uno de los motivos por los que en Java no se pueden manejar punteros), al final se demuestra que es un nido de bugs. Porque <strong>212 no son -44</strong>. Y esto puede ser un auténtico problema en algo tan visible como una fecha.</p>
<p>El mes de marzo es un mes muy especial. Su mes anterior es de longitud variable (28 ó 29 días) y el siguiente es de 30, siendo el propio marzo de 31. Ved el siguiente código:</p>
<pre class="brush:java">Calendar cal = new GregorianCalendar();
cal.set (Calendar.DAY_OF_MONTH, 30);
cal.set (Calendar.MONTH, 2);
System.out.println (cal.getTime ());
System.out.println (cal.getActualMaximum (Calendar.DAY_OF_MONTH));
cal.set (Calendar.MONTH, cal.get(Calendar.MONTH) -1);
System.out.println (cal.getActualMaximum (Calendar.DAY_OF_MONTH));</pre>
<p>Esencialmente, lo que hace es ponernos en 30 de marzo de este año y sacar por pantalla los siguientes datos:</p>
<ul>
<li>Fecha actual</li>
<li>Número de días del mes de marzo</li>
<li>Número de días del mes de&#8230; ¿febrero?</li>
</ul>
<p>Java, en su excelsa sabiduría, <strong>ha decidido que en este caso que 2-1=2</strong>. Porque al restar uno al mes nos quedamos en 30 de febrero o, lo que es lo mismo, 2 de marzo. Esta chorrada (obviamente en un código más complejo) nos tuvo en el trabajo una mañana entretenidos porque el número de días de los meses siempre eran 30 ó 31, incluído un <strong>inexistente febrero</strong>.</p>
<p>En parte fue una suerte que estuviéramos a 30 de marzo y no en 2 de abril, en cuyo caso nos daríamos cuenta del problema casi un año después de sacar el proyecto a producción. A veces Java es realmente odioso con su &#8220;<em>deja que la JVM piense por ti</em>&#8220;.</p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/XG_QIU0FWDk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/el-extrano-bug-del-calendar/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>mini, una biblioteca para procesar archivos INI</title>
		<link>http://blog.4bits.es/mini-una-biblioteca-para-procesar-archivos-ini/</link>
		<comments>http://blog.4bits.es/mini-una-biblioteca-para-procesar-archivos-ini/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 19:17:35 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Proyectos]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=437</guid>
		<description><![CDATA[Hace ya bastante tiempo en el trabajo me tocó lidiar con un programa (en C) que debía procesar la configuración de un archivo INI, para quién no lo sepa es un archivo de texto con un formato similar a este:
;Archivo INI

[sección]
clave1=valor1
clave2=valor2
En estos casos lo mejor es no reinventar la rueda, así que hice un par [...]]]></description>
			<content:encoded><![CDATA[<p>Hace ya bastante tiempo en el trabajo me tocó lidiar con <strong>un programa (en C) que debía procesar la configuración de un archivo INI</strong>, para quién no lo sepa es un archivo de texto con un formato similar a este:</p>
<pre class="brush:text">;Archivo INI

[sección]
clave1=valor1
clave2=valor2</pre>
<p>En estos casos lo mejor es no reinventar la rueda, así que hice un par de búsquedas por internet, pero lo que encontré no me gustó, así que ni corto ni perezoso realicé mi propio <em>cutre-parser</em> que funcionaba bien para lo que quería, archivos INI creados a mano, pero no para todos los casos que podría tener un archivo INI.</p>
<p>Así que gracias a un poco de tiempo libre me he puesto las pilas un poco y he ido modificando aquel <em>cutre-parser</em> hasta algo más decente, aunque todavía le quiero dar un par de vueltas para dejarlo bien. De todos modos, el código que hay ahora mismo funciona bastante bien, así que he creado un <a href="http://github.com/franchukelly/mini">repositorio para mini en github</a> (por cierto, git mola mil), así no tenéis excusa para probarlo.</p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/r44RHu8rP8w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/mini-una-biblioteca-para-procesar-archivos-ini/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Jornadas técnicas del GUL-UC3M</title>
		<link>http://blog.4bits.es/jornadas-tecnicas-gul-uc3m-2/</link>
		<comments>http://blog.4bits.es/jornadas-tecnicas-gul-uc3m-2/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 09:00:46 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[Noticias]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=434</guid>
		<description><![CDATA[Como viene siendo habitual ya están listas las jornadas técnicas del GUL de mi antigua universidad (la Carlos III de Madrid), estas jornadas se realizarán en las dos primeras semanas de Marzo.
En mi opinión hay bastantes charlas con temas muy interesantes, por ejemplo: seguridad en servidores, BOINC, OpenGL, Python, Ruby, &#8230; Así que si os [...]]]></description>
			<content:encoded><![CDATA[<p>Como viene siendo habitual ya están listas las jornadas técnicas del <a href="http://www.gul.es">GUL</a> de mi antigua universidad (la Carlos III de Madrid), estas jornadas se realizarán en las dos primeras semanas de Marzo.</p>
<p>En mi opinión hay bastantes charlas con temas muy interesantes, por ejemplo: seguridad en servidores, BOINC, OpenGL, Python, Ruby, &#8230; Así que si os interesa algún tema de estos, pasaos por allí, la entrada es gratuita y no hace falta ningún tipo de registro.</p>
<p>Enlace original: <a href="http://www.gul.es/index.php?view=article&#038;catid=1:latest-news&#038;id=73:calendario-de-marzo-2010">Jornadas técnicas (Marzo 2010) del GUL-UC3M</a></p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/JfNP9xCCU3g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/jornadas-tecnicas-gul-uc3m-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android Developer Lab 2010 (Madrid)</title>
		<link>http://blog.4bits.es/android-developer-lab-2010-madrid/</link>
		<comments>http://blog.4bits.es/android-developer-lab-2010-madrid/#comments</comments>
		<pubDate>Mon, 15 Feb 2010 08:53:29 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[Noticias]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=432</guid>
		<description><![CDATA[El sábado estuve en el Android Developer Lab 2010 de Madrid, y sí fui uno de los afortunados en conseguir un Nexus One gratis (se lo dieron a todos los asistentes).
En principio pensaba que el evento sería una especie de curso sobre cómo desarrollar una aplicación de Android, pero estaba equivocado, todo consistió en un [...]]]></description>
			<content:encoded><![CDATA[<p>El sábado estuve en el <a href="https://sites.google.com/site/androiddevlabs/">Android Developer Lab</a> 2010 de Madrid, y sí fui uno de los afortunados en conseguir un <a href="http://www.google.com/phone">Nexus One</a> gratis (se lo dieron a todos los asistentes).</p>
<p>En principio pensaba que el evento sería una especie de curso sobre cómo desarrollar una aplicación de Android, pero estaba equivocado, todo consistió en un poco de marketing de Android y luego las novedades de la nueva versión (la 2.1) de Android, para acabar con una ronda de preguntas de la gente.</p>
<p>En general, el evento no me gustó demasiado por no ser realmente técnico, pero que regalasen Nexus One hizo que valiese la pena. Y sí, en poco tiempo espero hablar por aquí de programación en Android.</p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/QXSiU6iqxko" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/android-developer-lab-2010-madrid/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Encapsulamiento</title>
		<link>http://blog.4bits.es/encapsulamiento/</link>
		<comments>http://blog.4bits.es/encapsulamiento/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 17:14:31 +0000</pubDate>
		<dc:creator>Lek</dc:creator>
				<category><![CDATA[Conceptos]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=420</guid>
		<description><![CDATA[Hoy toca otro post de teoría de la programación para hablar de uno de esos conceptos que muchas veces es difícil llevar a la práctica.
En algunos paradigmas de programación (como la programación orientada a objetos) se nos dice que desde fuera de una clase sólo necesitamos saber qué se hace, no el cómo. Si la [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy toca otro post de teoría de la programación para hablar de uno de esos conceptos que muchas veces es difícil llevar a la práctica.</p>
<p>En algunos paradigmas de programación (como la programación orientada a objetos) se nos dice que <strong>desde fuera de una clase sólo necesitamos saber qué se hace, no el cómo</strong>. Si la clase se encarga de interaccionar con una base de datos no necesita saber cuál es la base de datos ya que de eso se encargaría el driver (lo cual sería cierto si el estándar SQL fuera más&#8230; estándar&#8230; pero eso es otro tema). Y al resto de clases del proyecto no les importa tampoco cómo realiza esa interacción, sino que sólo deben preocuparse de que <em>tal</em> método devuelve los datos de la tabla <em>cual</em>.</p>
<p>¿Cómo se hace esto? Definiendo muy bien la <strong>visibilidad de la clase</strong>. Esto es, qué métodos se van a llamar desde el resto de clases (métodos públicos), cuáles están restringidos a clases “amigas” (del mismo paquete o que hereden de la nuestra, son los métodos protegidos) y cuáles no son accesibles en absoluto fuera de nuestra clase (métodos privados).</p>
<p>Por definición, es recomendable que todas las <strong>variables</strong> sean definidas como <strong>privadas</strong>, de forma que la única manera de manipularlas sea a través de los métodos públicos definidos por la clase y que sean éstos los que se encarguen de hacer todas las comprobaciones que sean necesarias.</p>
<p>Imaginemos la siguiente clase muy básica:</p>
<pre class="brush:java">public class Persona {

  private String nombre;
  private int edad;

  public Persona () {
    inicializar ();
  }

  public void setNombre (String nombre2) {
    nombre = nombre2;
  }

  public void setEdad (int edad2) {
    if (edad2 > 0) {
      edad = edad2;
    }
  }

  public boolean validaVariables () {
    return edad > 0 &#038;&#038; ! "".equals(nombre);
  }

  private void inicializar () {
    nombre = "";
    edad = 0;
  }
}</pre>
<p>En este caso, lo que vemos desde fuera es que para la clase Persona podemos asignar una variable <em>nombre</em> y una variable <em>edad</em>. Podría haber más, pero no nos interesan puesto que no podemos interaccionar con ellas.</p>
<p>Además disponemos de una función para validar que los datos son correctos, pero nunca sabremos desde otra clase que existe un método <em>inicializar</em>.</p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/Wf7yoqRQDlk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/encapsulamiento/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Manifiesto en defensa de los derechos fundamentales en internet</title>
		<link>http://blog.4bits.es/manifiesto-en-defensa-de-los-derechos-fundamentales-en-internet/</link>
		<comments>http://blog.4bits.es/manifiesto-en-defensa-de-los-derechos-fundamentales-en-internet/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 08:04:39 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[Noticias]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=416</guid>
		<description><![CDATA[Ante la inclusión en el Anteproyecto de Ley de Economía sostenible de modificaciones legislativas que afectan al libre ejercicio de las libertades de expresión, información y el derecho de acceso a la cultura a través de Internet, los periodistas, bloggers, usuarios, profesionales y creadores de internet manifestamos nuestra firme oposición al proyecto, y declaramos que:

Los [...]]]></description>
			<content:encoded><![CDATA[<p>Ante la inclusión en el Anteproyecto de Ley de Economía sostenible de modificaciones legislativas que afectan al libre ejercicio de las libertades de expresión, información y el derecho de acceso a la cultura a través de Internet, los periodistas, bloggers, usuarios, profesionales y creadores de internet manifestamos nuestra firme oposición al proyecto, y declaramos que:</p>
<ol>
<li><strong>Los derechos de autor no pueden situarse por encima de los derechos fundamentales de los ciudadanos</strong>, como el derecho a la privacidad, a la seguridad, a la presunción de inocencia, a la tutela judicial efectiva y a la libertad de expresión.</li>
<li><strong>La suspensión de derechos fundamentales es y debe seguir siendo competencia exclusiva del poder judicial.</strong> Ni un cierre sin sentencia. Este anteproyecto, en contra de lo establecido en el artículo 20.5 de la Constitución, pone en manos de un órgano no judicial -un organismo dependiente del ministerio de Cultura-, la potestad de impedir a los ciudadanos españoles el acceso a cualquier página web.</li>
<li><strong>La nueva legislación creará inseguridad jurídica en todo el sector tecnológico español</strong>, perjudicando uno de los pocos campos de desarrollo y futuro de nuestra economía, entorpeciendo la creación de empresas, introduciendo trabas a la libre competencia y ralentizando su proyección internacional.</li>
<li><strong>La nueva legislación propuesta amenaza a los nuevos creadores y entorpece la creación cultural.</strong> Con Internet y los sucesivos avances tecnológicos se ha democratizado extraordinariamente la creación y emisión de contenidos de todo tipo, que ya no provienen prevalentemente de las industrias culturales tradicionales, sino de multitud de fuentes diferentes.</li>
<li><strong>Los autores, como todos los trabajadores, tienen derecho a vivir de su trabajo con nuevas ideas creativas, modelos de negocio y actividades asociadas a sus creaciones.</strong> Intentar sostener con cambios legislativos a una industria obsoleta que no sabe adaptarse a este nuevo entorno no es ni justo ni realista. Si su modelo de negocio se basaba en el control de las copias de las obras y en Internet no es posible sin vulnerar derechos fundamentales, deberían buscar otro modelo.</li>
<li><strong>Consideramos que las industrias culturales necesitan para sobrevivir alternativas modernas, eficaces, creíbles y asequibles y que se adecuen a los nuevos usos sociales</strong>, en lugar de limitaciones tan desproporcionadas como ineficaces para el fin que dicen perseguir.</li>
<li><strong>Internet debe funcionar de forma libre y sin interferencias políticas</strong> auspiciadas por sectores que pretenden perpetuar obsoletos modelos de negocio e imposibilitar que el saber humano siga siendo libre.</li>
<li><strong>Exigimos que el Gobierno garantice por ley la neutralidad de la red en España</strong>, ante cualquier presión que pueda producirse, como marco para el desarrollo de una economía sostenible y realista de cara al futuro.</li>
<li><strong>Proponemos una verdadera reforma del derecho de propiedad intelectual</strong> orientada a su fin: devolver a la sociedad el conocimiento, promover el dominio público y limitar los abusos de las entidades gestoras.</li>
<li><strong>En democracia las leyes y sus modificaciones deben aprobarse tras el oportuno debate público</strong> y habiendo consultado previamente a todas las partes implicadas. No es de recibo que se realicen cambios legislativos que afectan a derechos fundamentales en una ley no orgánica y que versa sobre otra materia.</li>
</ol>
<p>Este manifiesto es obra de muchas manos, y propiedad de todos. Si te gusta, cópialo, pásalo, publícalo en tu blog o haz lo que quieras con él.</p>
<p>Aunque llego con dos días de retraso, como se suele decir <em>más vale tarde que nunca</em>. Por cierto, para hoy (4 de Diciembre) hay convocada una <del datetime="2009-12-04T12:17:15+00:00">manifestación</del> concentración en diferentes ciudades de España, en Madrid será frente al ministerio de cultura a las ocho de la tarde.</p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/3RZBQzvdYxE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/manifiesto-en-defensa-de-los-derechos-fundamentales-en-internet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Los modelos de django</title>
		<link>http://blog.4bits.es/los-modelos-de-django/</link>
		<comments>http://blog.4bits.es/los-modelos-de-django/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 19:06:39 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=400</guid>
		<description><![CDATA[En el anterior post de introducción a django, no se usaron bases de datos, así que en este se verá cómo trabaja django con las bases de datos, es algo realmente sencillo.
Los modelos
Al basarse django en el MVC, divide la aplicación en dos partes la vista (que ya se pudo ver en el anterior post) [...]]]></description>
			<content:encoded><![CDATA[<p>En el anterior <a href="http://blog.4bits.es/primeros-pasos-con-django/">post de introducción a django</a>, no se usaron bases de datos, así que en este se verá cómo trabaja django con las bases de datos, es algo realmente sencillo.</p>
<h3>Los modelos</h3>
<p><strong>Al basarse django en el <abbr title="Modelo-Vista-Controlador">MVC</abbr>, divide la aplicación en dos partes la vista (que ya se pudo ver en el anterior post) y el modelo.</strong> El modelo define los datos que utilizará la aplicación, como podrían ser los datos de un usuario (nombre, apellidos, dirección, &#8230;).</p>
<p>En el caso de django, <strong>los modelos serán clases de python que heredarán la clase <code>Model</code> y que utilizarán unos tipos de datos especiales para definir sus atributos.</strong> Más tarde, django, gracias a su <abbr title="Object-Relational Mapping">ORM</abbr>, transformará estas clases en tablas de la base de datos del proyecto.</p>
<h3>Creando un modelo</h3>
<p>Los modelos se definen en el archivo «models.py» de la aplicación de django que los vaya a utilizar. Cada modelo será una clase de python que heredará la clase <code>django.db.models.Model</code>, los atributos de las clases de cada modelo deberán ser instancias de unas clases que ofrece django para poder traducir estos atributos en campos de las tablas de la base de datos. Por ejemplo, para crear el modelo de un usuario:</p>
<pre class="brush:python"># models.py
# -*- coding: utf-8 -*-

from django.db import models

class Usuario (models.Model):
    """Datos del usuario utilizados en la aplicación."""

    nombre = models.CharField (max_length=40)
    apellidos = models.CharField (max_length=60)
    email = models.EmailField (unique=True)

    def __unicode__ (self):
        return '%s %s (%s)' % (self.nombre, self.apellidos, self.email)</pre>
<p>Una breve explicación sobre el ejemplo anterior:</p>
<ul>
<li>Los atributos <code>nombre</code> y <code>apellidos</code> serán dos campos de texto con una longitud máxima de 40 y de 60 caracteres respectivamente en la base de datos.</li>
<li>El atributo <code>email</code> será un campo de texto cuyo valor deberá ser único y que además sólo aceptará direcciones de correo electrónico bien formadas.</li>
<li>El método <code>__unicode__</code> es el equivalente a <code>__str__</code> en python, es decir, se usará cuando se quiera mostrar una instancia de la clase como una cadena de caracteres.</li>
</ul>
<p>Para conocer los tipos existentes para los atributos de los modelos, siempre se puede consultar <a href="http://docs.djangoproject.com/en/1.1/ref/models/fields/#ref-models-fields">la lista de los tipos de los modelos de django</a>.</p>
<p>Una vez se tengan los modelos creados, se deberán <em>sincronizar</em> con la base de datos utilizada.</p>
<h3>Configurando la base de datos</h3>
<p>Configurar la base de datos a utilizar en django es muy sencillo, sólo hay que editar el archivo «settings.py» del proyecto. Concretamente las siguientes variables:</p>
<ul>
<li><code>DATABASE_ENGINE</code> indica el gestor de base de datos utilizado, actualmente django sólo dispone de los siguientes módulos: postgresql_psycopg2, postgresql, mysql, sqlite3 u oracle.</li>
<li><code>DATABASE_NAME</code> indica el nombre de la base de datos, menos en el caso de sqlite3 que indica la ruta al archivo de la base de datos.</li>
<li><code>DATABASE_USER</code> indica el usuario con acceso a la base de datos anterior.</li>
<li><code>DATABASE_PASSWORD</code> indica la contraseña del usuario anterior.</li>
<li><code>DATABASE_HOST</code> indica la dirección del servidor de la base de datos, se debe dejar vacío para la máquina local.</li>
<li><code>DATABASE_PORT</code> indica el puerto del servidor de la base de datos, se debe dejar vacío para usar el puerto predeterminado.</li>
</ul>
<p><strong>Aviso:</strong> El usuario, la contraseña, la dirección y el puerto del servidor no se usan con sqlite3, ya que no son necesarios.</p>
<p>Una vez configurada la base de datos y creados los modelos necesarios, se podrá <em>sincronizar</em> los modelos de las aplicaciones del proyecto con la base de datos, sólo hay que ejecutar:</p>
<pre>$ python manage.py syncdb</pre>
<p><strong>Nota:</strong> Hay que recordar que las aplicaciones del proyecto aparecen en la variable <code>INSTALLED_APPS</code> del archivo «settings.py», yo recomendaría (para estos ejemplos) quitar o comentar las que vienen de manera predeterminada.</p>
<h3>Trabajando con la base de datos</h3>
<p>Esta es una de las mejores cosas que tiene django, y es que para acceder (ya sea para consultar, insertar, actualizar o borrar una entrada) a la base de datos, gracias al ORM sólo se usan las clases definidas como modelos.</p>
<p>Para probar todo lo que se va a explicar sin tener que crearse vistas (que todavía no se han explicado en profundidad) siempre se puede ejecutar la consola de django:</p>
<pre>$ python manage.py shell</pre>
<h4>Insertar, actualizar y borrar entradas</h4>
<p>Tomando como ejemplo la clase <code>Usuario</code> anterior, se podría realizar:</p>
<pre class="brush:python">from proyecto.aplicación.models import Usuario

# Insertar un nuevo usuario
usuario = Usuario (nombre='Pepe', apellidos='Garcia',
                   email='pepe@garcia.es')
usuario.save ()

# Actualizar los datos del usuario
usuario.nombre = 'Jose'
usuario.save ()

# Borrar el usuario
usuario.delete ()</pre>
<p>Como se puede ver es tan sencillo como trabajar con cualquier clase de python.</p>
<h4>Los «QuerySets»</h4>
<p>Los «QuerySets» son conjuntos de objetos de la base de datos, es decir, los resultados de una consulta a la base de datos en forma de objetos de python.</p>
<p>Las clases de los modelos disponen de una instancia del gestor de objetos de la base de datos <code>Clase.objects</code>, en esta instancia se definen los diferentes métodos para realizar las consultas sobre la base de datos, que devolverán un «QuerySet» que contendrá los resultados.</p>
<p>De este modo, tomando el ejemplo de la clase <code>Usuario</code>:</p>
<pre class="brush:python">from proyecto.aplicación.models import Usuario

# Insertar varios usuarios
usuario = Usuario (nombre='Pepe', apellidos='Garcia',
                   email='pepe@garcia.es')
usuario.save ()

usuario = Usuario (nombre='Maruja', apellidos='Perez',
                   email='maruja@perez.es')
usuario.save ()

usuario = Usuario (nombre='Pedro', apellidos='Garcia',
                   email='pedro@garcia.es')
usuario.save ()

# Conseguir todas las entradas de la base de datos
todos_los_usuarios = Usuario.objects.all ()
print 'Todos los usuarios %s' % todos_los_usuarios

# Conseguir los usuarios que se apelliden Garcia
garcias = Usuario.objects.filter (apellidos='Garcia')
print 'La familia Garcia %s' % garcias

# La familia Garcia ordenada por nombre
print 'La familia Garcia ordenada por nombre %s' % garcias.order_by ('name')</pre>
<p>Como siempre esto no es más que una mota de polvo de lo que en realidad se puede hacer, para profundizar lo mejor es consultar <a href="http://docs.djangoproject.com/en/1.1/topics/db/queries/#topics-db-queries">la documentación de django sobre los «QuerySets»</a>.</p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/cfUVkDXyeC4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/los-modelos-de-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo proteger las contraseñas de los usuarios</title>
		<link>http://blog.4bits.es/como-proteger-las-contrasenas-de-los-usuarios/</link>
		<comments>http://blog.4bits.es/como-proteger-las-contrasenas-de-los-usuarios/#comments</comments>
		<pubDate>Sun, 22 Nov 2009 18:53:58 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Seguridad]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=396</guid>
		<description><![CDATA[Voy a recuperar otro de mis documentos perdidos en Google Docs (el anterior fue el de las autotools), esta vez se trata de un pequeño manual sobre cómo proteger las contraseñas de lo usuarios de cualquier aplicación que se programe, el manual es una traducción al español del artículo How to encrypt user passwords de [...]]]></description>
			<content:encoded><![CDATA[<p>Voy a recuperar otro de mis documentos perdidos en Google Docs (el anterior fue el de <a href="http://blog.4bits.es/autotools/">las autotools</a>), esta vez se trata de un pequeño manual sobre cómo proteger las contraseñas de lo usuarios de cualquier aplicación que se programe, el manual es una traducción al español del artículo <a href="http://www.jasypt.org/howtoencryptuserpasswords.html">How to encrypt user passwords</a> de Daniel Fernandez.</p>
<h3>1. Visión general</h3>
<p><strong>Casi todas las aplicaciones web modernas necesitan</strong>, de un modo u otro, <strong>cifrar las contraseñas de sus usuarios.</strong> Se podría decir que, desde el momento en que la aplicación tiene usuarios, y los usuarios se identifican usando una contraseña, <strong>esas contraseñas se deben guardar usando algún tipo de cifrado.</strong></p>
<p>Hay muchas razones básicas para esto: las bases de datos pueden estar comprometidas, y por tanto también las comunicaciones. Pero la razón más importante es que se tiene que pensar que las contraseñas de los usuarios son datos personales. Sus contraseñas son sus claves para su privacidad, por tanto son personales, y nadie tiene el derecho de conocerlas. Y se debe cumplir esto si se quiere ganar la confianza de los usuarios.</p>
<h3>2. El algoritmo</h3>
<p>Ahora que se quieren cifrar las contraseñas, se debe saber cómo. Aquí entra la primera regla:</p>
<blockquote><p>I. Cifrar las contraseñas usando técnicas de un sentido, es decir, funciones resumen (o <em>hash</em>).</p></blockquote>
<p>Esto se debe a que, excepto para algunos escenarios específicos, no hay ninguna razón para que una contraseña sea descifrada. Si se cifran las contraseñas usando cifrados basados en claves (una técnica de dos sentidos) y un atacante consigue saber la clave de cifrado, se revelarán todas las contraseñas. Si no se tiene una clave para el cifrado, el riesgo desaparece, y el atacante tendrá que confiar en el uso de técnicas de fuerza bruta o similares.</p>
<p>Pero, ¿qué ocurre si un usuario pierde su contraseña? ¿No podrá recuperarla? La respuesta es NO. No sólo no se puede recuperar, si no que ni siquiera existe una manera de leer/conocer/ver las contraseñas de los usuarios, no importa si se es el administrador del sistema. Si un usuario pierde su contraseña, sólo se podrá reiniciarla a un nuevo valor y enviárselo por algún canal seguro al usuario, y pidiéndole que la cambie lo más pronto que pueda.</p>
<p>Ahora que está claro que las funciones resumen son necesarias en las contraseñas, ¿cuál algoritmo se debería usar? Hay bastantes, y dependen de las necesidades de cada uno. Los más usados son:</p>
<ul>
<li>Algoritmo MD5.</li>
<li>Familia SHA: SHA-1 y la variantes de SHA-2 (SHA-224, SHA-256, SHA-384 y SHA-512)</li>
</ul>
<p>En la mayoría de los casos, MD5 o SHA-1 serán elecciones adecuadas para los resúmenes de contraseñas, aunque aplicar estos algoritmos no será suficiente, como se verá a continuación.</p>
<p>Cuando se dice que se deberían usar funciones resumen para los cifrados de las contraseñas, y dado que estas funciones resumen son técnicas de un sentido, la siguiente pregunta es: «Si no se pueden descifrar las contraseñas, ¿cómo se comprueba que un usuario tiene una contraseña correcta?»</p>
<p>Hay una respuesta muy simple a esta cuestión, que será la segunda regla:</p>
<blockquote><p>II. La entrada y las contraseñas guardadas se comparan usando los resultados de las funciones resumen, no usando cadenas sin cifrar.</p></blockquote>
<p>Lo que significa que, una vez los usuarios han introducido sus contraseñas en la identificación, se realizará la función resumen sobre la contraseña introducida con el mismo algoritmo que se ha usado con las contraseñas guardadas, y se compararán ambos resultados. Como estas funciones garantizan que dos entradas iguales obtienen el mismo resultado (lo que no es cierto en el sentido contrario), si los resultados coinciden se considerará que la contraseña introducida por el usuario es correcta.</p>
<h3>3. Mejorando la seguridad de los resúmenes</h3>
<p>Todos los algoritmos de funciones resumen mencionados anteriormente comparten una característica: son públicos. Son algoritmos muy conocidos y ampliamente implementados, por lo que cualquiera puede usarlos.</p>
<p>Si cualquiera puede usar el mismo algoritmo que la aplicación, y por alguna razón los atacantes pueden ver la base de datos de los resúmenes de las contraseñas, ¿cómo se puede estar seguro que los atacantes no serán capaces de conseguir alguna contraseña de los usuarios probando todas las posibilidades hasta que encuentren algún resumen que coincida con uno de los guardados?</p>
<p>La respuesta es que no se puede. Pero se puede hacer que todo eso sea una tarea enorme y con un gran tiempo de realización, de modo que no resulte útil, a menos que puedan esperar toda la eternidad. Para lograr esto, se van a explicar dos conceptos: «salt» y el contador de iteración.</p>
<h4>3.1. «Salt»</h4>
<p>«Salt» es una secuencia de bytes que se añaden a la contraseña antes de conseguir su resumen. Esto hace que estos resúmenes sean diferentes a los que deberían ser usando sólo la contraseña, y como resultado se consigue protección contra los ataques de diccionario. Se pueden seguir dos estrategias para usar «salt»:</p>
<ul>
<li>Usar un «salt» fijo, una secuencia de bytes que se utilizarán para resumir cualquier contraseña. Se puede guardar oculto el «salt» y considerarlo un valor añadido de seguridad, pero esto puede hacer que el sistema se vuelva más vulnerable a ataques de cumpleaños y, en general, a ataques dirigidos contra la base de datos de contraseñas.</li>
<li>Usar un «salt» variable, que normalmente es una opción segura (especialmente si es aleatorio). Este se genera independientemente para cada contraseña a resumir, y permite que cada contraseña guardada esté desacoplada de las demás, creando una gran protección general y un alta seguridad contra ataques dirigidos contra la base de datos de contraseñas.</li>
</ul>
<p>En la práctica, un «salt» aleatorio (o variable) es la mejor idea porque, aunque al generarse aleatoriamente tendrá que guardarse junto al resumen de la contraseña (por lo que cualquiera podrá recuperarlo) y esto hará que sea trivial para un atacante conocerlo, permitirá que cada contraseña de usuario sea independiente del resto, por lo que tendrán que atacarse una por una.</p>
<p>Se tiene que pensar que, si se usa un «salt» fijo y el atacante consigue saberlo, la seguridad de toda la base de datos de contraseñas será nula. Y hay muchos métodos para que el atacante pueda conocer este «salt», como aplicar fuerza bruta en sus contraseñas o en contraseñas que tenga de algún usuario válido. En un escenario de un «salt» fijo, una contraseña débil podría hacer que el sistema de contraseñas fuera débil.</p>
<p>Sin embargo, si se quiere mantener una parte del «salt» en secreto, se puede usar una técnica que mezcle las otras dos, usando un «salt» compuesto de una parte fija y otra aleatoria, guardando los bytes aleatorios junto al resumen de la contraseña.</p>
<p>El tamaño mínimo de un «salt» es de 8 bytes. Si se usa una opción mixta, al menos 8 bytes deberían ser aleatorios.</p>
<p>Así, se puede definir la tercera regla:</p>
<blockquote><p>III. Se debe usar un «salt» que contenga al menos 8 bytes aleatorios, y añadir esos bytes junto al resumen de la contraseña.</p></blockquote>
<h4>3.2. El contador de iteración</h4>
<p>El contador de iteración es el número de veces que la función <em>hash</em> que realiza el resumen se aplica a sus propios resultados.</p>
<p>Esto significa que, una vez se ha seleccionado un «salt» y concatenado con la contraseña, se deberá aplicar la función <em>hash</em> (por ejemplo, MD5), conseguir el resultado, y pasarlo de nuevo como entrada a la misma función, y hacer lo mismo las veces que indique el contador de iteración.</p>
<p>El número mínimo recomendado de iteraciones es 1.000, y esto proporcionará una buena seguridad extra. Hay que pensar que, cuando se crea un único resumen de una contraseña para un nuevo usuario, la diferencia entre aplicar la función <em>hash</em> una vez o 1.000 veces no será un problema, tal vez doscientos milisegundos, pero los atacantes deberán tener que generar una enorme cantidad de intentos de resumen mediante fuerza bruta y, para un atacante, la diferencia entre aplicar la función <em>hash</em> una vez y aplicarla mil veces para cada intento será un gran problema computacional.</p>
<p>Así, se obtiene la cuarta regla:</p>
<blockquote><p>IV. Iterar la función <em>hash</em> al menos 1.000 veces.</p></blockquote>
<h3>4. Secuencia de traducción de caracteres a secuencia de bytes</h3>
<p>Antes de poder guardar correctamente los resúmenes de las contraseñas, hay algo que se debería tener en cuenta, que es la diferencia entre cadenas de caracteres y secuencias de bytes: dos cadenas de caracteres se pueden representar con diferentes secuencias de bytes dependiendo de la codificación empleada (ISO-8859-1, UTF-8, &#8230;)</p>
<p>Esto afecta, ya que las contraseñas suelen ser cadenas de caracteres, pero las funciones <em>hash</em> trabajan a nivel de byte.</p>
<h4>4.1. Problemas codificando la contraseña introducida</h4>
<p>En el supuesto de que un nuevo usuario se identifique con una contraseña que no contiene caracteres ASCII, y que la aplicación de identificación, que se está ejecutándo en Windows 2000 en Europa Occidental, convierta la cadena de caracteres a bytes sin elegir una codificación específica para la operación, e incluso usando la que haya de forma predeterminada, en Windows suele ser ISO-8859-1. De modo que el resumen se realice sobre esa secuencia de bytes y quede almacenado.</p>
<p>Entonces, este usuario vuelve de nuevo y esta vez no visita la aplicación de identificación anterior, en vez de eso usa cualquier otra aplicación con la misma base de datos de contraseñas pero en Linux. El usuario introduce correctamente su contraseña y &#8230; ¡no coincide!</p>
<p>¿Por qué? Porque la mayoría de los sistemas Linux, usan UTF-8 como codificación predeterminada, y las contraseñas que ha introducido el usuario en ambos casos se han codificado en diferentes secuencias de bytes, afectando a la correcta concordancia de las contraseñas.</p>
<p>Cómo se puede resolver esto, pues utilizando una codificación fija para las codificaciones de las cadena de caracteres a secuencia de bytes. Así se enuncia la quinta regla:</p>
<blockquote><p>V. Antes de resumir, realizar una codificación de cadena de caracteres a secuencia de bytes usando una codificación fija, preferiblemente UTF-8.</p></blockquote>
<p>Si se usa Java, donde las cadenas de caracteres (clases <code>String</code>) se codifican independientemente (aunque usan de fondo UTF-16), no habrá que preocuparse de si la aplicación usa ISO-8859-1 o alguna otra codificación en lugar de UTF-8 para su interfaz de usuario, al igual que no será necesario que la codificación para los resúmenes de las contraseñas coincidan con las de la interfaz de usuario. Sólo será necesario que la codificación sea una fija, y UTF-8 proporciona un buen equilibrio entre tamaño y conjunto de caracteres.</p>
<h4>4.2. Problemas codificando en el almacenamiento del resumen</h4>
<p>Normalmente se quiere gestionar y almacenar el resumen de contraseñas como una cadena de caracteres, pero la función <em>hash</em> dará como resultado una secuencia de bytes que no necesariamente representará un carácter válido en alguna codificación. Por esto, la secuencia de bytes del resumen no se puede codificar en una cadena de caracteres, habiendo peligro de pérdidas de datos si se realizase.</p>
<p>Aquí es donde entra al rescate la codificación BASE64. Codificando la secuencia de bytes del resumen en BASE64, se asegura que la secuencia de bytes de salida representa una cadena de caracteres US-ASCII válida. Por lo que se podrá codificar una secuencia de bytes en BASE64 en una cadena de caracteres US-ASCII.</p>
<blockquote><p>VI. Finalmente, se debe aplicar la codificación BASE64 y guardar el resumen como una cadena de caracteres US-ASCII.</p></blockquote>
<h3>5. Resumen de las reglas para el cifrado de contraseñas</h3>
<p>La lista completa de reglas a aplicar:</p>
<ol>
<li>Cifrar las contraseñas usando técnicas de un sentido, es decir, funciones resumen (o <em>hash</em>).</li>
<li>La entrada y las contraseñas guardadas se comparan usando los resultados de las funciones resumen, no usando cadenas sin cifrar.</li>
<li>Se debe usar un «salt» que contenga al menos 8 bytes aleatorios, y añadir esos bytes junto al resumen de la contraseña.</li>
<li>Iterar la función <em>hash</em> al menos 1.000 veces.</li>
<li>Antes de resumir, realizar una codificación de cadena de caracteres a secuencia de bytes usando una codificación fija, preferiblemente UTF-8.</li>
<li>Finalmente, se debe aplicar la codificación BASE64 y guardar el resumen como una cadena de caracteres US-ASCII.</li>
</ol>
<h3>6. Realizándolo en Java</h3>
<p>La forma más sencilla de <a href="http://www.jasypt.org/encrypting-passwords.html">cifrar contraseñas en Java</a>, mediante las técnicas explicadas es usar Jasypt.</p>
<p>Si no se puede usar jasypt, o si por alguna razón se quiere desarrollar alguna característica de cifrado propia, se necesitarán:</p>
<ul>
<li>La clase <code>java.security.MessageDigest</code> para crear resúmenes. Esta clase permite especificar el algoritmo que se va a usar.</li>
<li>La clase <code>java.security.SecureRandom</code> para generar «salt» aleatorios de una manera segura, usando algoritmos como <code>SHA1PRNG</code>.</li>
<li>El método <code>java.lang.String.getBytes (String charsetName)</code>, para obtener una secuencia de bytes desde una cadena de caracteres, especificando una codificación fija (UTF-8).</li>
<li>La clase <code>org.apache.commons.codec.binary.Base64</code>, parte de la biblioteca Apache Commons-Codec, para realizar codificaciones BASE64 en la salida de la función <em>hash</em>.</li>
</ul>
<p>También, se puede utilizar el código fuente para las clases <code>org.jasypt.digest.StandardByteDigester</code> y <code>org.jasypt.digest.StandardStringDigester</code>, disponible en <a href="http://www.jasypt.org/source-repository.html">el repositorio de jasypt</a>.</p>
<h3>7. Defensa frente a los típicos ataques</h3>
<h4>7.1. Ataques de fuerza bruta</h4>
<p>Realizado sobre: Una única contraseña.</p>
<p>Descripción: El atacante intenta conseguir la contraseña del usuario generando todas las contraseñas posibles, resumiéndolas y probando si coinciden con el resumen de la contraseña del usuario.</p>
<p>Defensa: La iteración de la función <em>hash</em> un número de veces, como 1.000 (mínimo recomendado), el coste de la creación del resumen de la contraseña en el tiempo de identificación del usuario no es significante, pero el coste de un ataque de fuerza bruta por parte de un atacante que genera millones de resúmenes será muy grande. Hay que recordar que una de las mejores maneras de proteger los datos cifrados es haciendo que el coste de romper la seguridad sea más alto de lo que cuesta el esfuerzo.</p>
<h4>7.2. Ataques de diccionario</h4>
<p>Realizado sobre: Cada contraseña o una base de datos de contraseñas</p>
<p>Descripción: El atacante intenta conseguir la contraseña de un usuario comparando sus resúmenes contra un conjunto de resúmenes de contraseñas más probables, normalmente se generan desde una lista de palabras de un diccionario. Este ataque explota una debilidad actual de las aplicaciones, ya que muchos usuarios usan palabras del diccionario como contraseña.</p>
<p>Defensa: Añadiendo un «salt» aleatorio, la debilidad de las contraseñas basadas en diccionario se reduce, y la posibilidad de de que el resumen aparezca en un conjunto de resúmenes previamente creados por el atacante es mínima.</p>
<h4>7.3. Ataques de cumpleaños</h4>
<p>Realizado sobre: La base de datos de las contraseñas.</p>
<p>Descripción: Este ataque explota la paradoja del cumpleaños, la cual en resumen consiste en, teniendo un gran conjunto de resúmenes de contraseñas, las posibilidades de generar una contraseña cuyo resumen coincida con al menos uno de los resúmenes en el conjunto es mucho más alto que lo esperado. Y estas posibilidades aumentan bastante cuando el tamaño del conjunto (el número de usuarios) aumenta.</p>
<p>Defensa: Añadiendo un «salt» aleatorio las posibilidades de que un ataque de cumpleaños tenga éxito son mínimas, porque el atacante tendría que atacar cada contraseña por separado, y no el conjunto de contraseñas, para encontrar una coincidencia. Esto es porque se tendría que encontrar una contraseña que crease el mismo resumen que el del atacante usando el mismo «salt» que se usó para el resumen, y que es diferente para cada contraseña haciendo que el ataque pase a ser de fuerza bruta.</p>
<p>Espero que este pequeño manual os sea de utilidad, a mí me sirvió para mi <abbr title="Proyecto Fin de Carrera">PFC</abbr>.</p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/YgzeZ-AIlj8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/como-proteger-las-contrasenas-de-los-usuarios/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Primeros pasos con django</title>
		<link>http://blog.4bits.es/primeros-pasos-con-django/</link>
		<comments>http://blog.4bits.es/primeros-pasos-con-django/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 08:37:42 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=377</guid>
		<description><![CDATA[Hace tiempo estuve aprendiendo a programar en Python porque me apeteció y porque me tocó lidiar en el trabajo con una aplicación web, la cual realicé en django.
¿Qué es django?
Django es un entorno de desarrollo (lo que en inglés se denomina framework) para la creación rápida de aplicaciones web, basándose en el MVC (Modelo-Vista-Controlador).
Entre todas [...]]]></description>
			<content:encoded><![CDATA[<p>Hace tiempo <a href="http://blog.4bits.es/learning-python/">estuve aprendiendo a programar en Python</a> porque me apeteció y porque me tocó lidiar en el trabajo con una aplicación web, la cual realicé en <a href="http://www.djangoproject.com/">django</a>.</p>
<h3>¿Qué es django?</h3>
<p>Django es un entorno de desarrollo (lo que en inglés se denomina <em>framework</em>) para la creación rápida de aplicaciones web, basándose en el MVC (Modelo-Vista-Controlador).</p>
<p>Entre todas las posibilidades que ofrece están que <strong>permite trabajar con las bases de datos como si no existieran, la creación de URL bonitas sin tener que tocar nada del servidor web, el uso de plantillas en (X)HTML para la creación de las diferentes páginas, y muchas cosas más</strong>, todas ellas estupendas y supongo que todas ellas también las tendrán otros entornos similares que utilicen otros lenguajes de programación.</p>
<h3>Iniciando un nuevo proyecto</h3>
<p>Lo primero que se debe hacer en django es crear lo que se denomina un proyecto, éste a su vez contendrá aplicaciones que serán las que contengan el código utilizado en la aplicación web. Por poner un ejemplo: el proyecto sería un <abbr title="Sistema de Gestión de Contenidos">CMS</abbr> y las aplicaciones las diferentes funcionalidades de dicho <abbr title="Sistema de Gestión de Contenidos">CMS</abbr>.</p>
<p>Para ello se deberá ejecutar:</p>
<pre>$ django-admin.py startproject nombre_del_proyecto</pre>
<p>Esto creará un directorio, llamado «nombre_del_proyecto», con los archivos básicos de todo proyecto de django:</p>
<ul>
<li><code>__init__.py</code> es el archivo de inicialización de cualquier paquete de python.</li>
<li><code>manage.py</code> permitirá la gestión del proyecto de django, como: crear las aplicaciones del proyecto, crear las bases de datos, ejecutar un servidor web para probar el proyecto, &#8230;</li>
<li><code>settings.py</code> contiene la configuración del proyecto, básicamente contiene un montón de variables que utilizará django para la configuración.</li>
<li><code>urls.py</code> contiene los patrones de las direcciones de las diferentes vistas del proyecto de django.</li>
</ul>
<p>Lo malo es que sólo con esto no se va a poder hacer nada más que cambiar unos cuantos valores de la configuración, para que un proyecto haga algo deberá tener al menos una aplicación que contendrá el código necesario.</p>
<h3>Iniciando una nueva aplicación</h3>
<p>Para crear una aplicación se debe usar el archivo «manage.py» del proyecto del siguiente modo:</p>
<pre>$ python manage.py startapp nombre_de_la_aplicación</pre>
<p>Esto creará un directorio, llamado «nombre_de_la_aplicación», con los archivos básicos de toda aplicación de django:</p>
<ul>
<li><code>__init__.py</code> igual que antes, es el archivo de inicialización de cualquier paquete de python.</li>
<li><code>models.py</code> contendrá los modelos de la aplicación, estos modelos son clases de python que se traducirán en tablas en la base de datos.</li>
<li><code>tests.py</code> contendrá tests de la aplicación. <strong>Nota:</strong> Este archivo sólo se crea a partir de la versión 1.1 de django.</li>
<li><code>views.py</code> contendrá las vistas de la aplicación, estas vistas son funciones de python que realizarán las tareas necesarias para mostrar el resultado como una página web.</li>
</ul>
<p>Para que esta aplicación esté disponible en el proyecto, hay que añadirla a la lista de aplicaciones del proyecto que está en el archivo «settings.py».</p>
<pre>INSTALLED_APPS = (
    'hello_world.hello_app',
)</pre>
<p><strong>Nota:</strong> Cuando se crea un nuevo proyecto django crea una lista de aplicaciones predeterminada, que en este caso daría lo mismo borrarlas.</p>
<h3>Creando un «hola mundo»</h3>
<p><strong>Lo primero será crear un proyecto («hello_world») y una aplicación («hello_app») para dicho proyecto</strong>, tal y como se ha mencionado antes. Una vez hecho, se deberá crear una vista para la página web.</p>
<h4>Creando una vista</h4>
<p>Para la creación de una vista, se debe editar el archivo «views.py» de la aplicación creada del siguiente modo:</p>
<pre class="brush:python"># views.py
# -*- coding: utf-8 -*-
# Views used in hello world application.

from django.shortcuts import render_to_response

def hello (request):
    """Hello view function."""

    return render_to_response ('hello.htm',
                               { 'hello_msg' : '¡Hola mundo!' })
</pre>
<p>La función <code>render_to_response</code> usa una plantilla (que ahora se explicará) para crear la página web de la vista.</p>
<h4>Creando una plantilla</h4>
<p>Django dispone de un lenguaje propio para la creación de plantillas, básicamente son archivos HTML con unas etiquetas especiales, que se marcan con llaves dobles, que django se encargará de rellenar.</p>
<p>De este modo, crear una plantilla es tan sencillo como crear un archivo HTML en un directorio llamado «templates» dentro del directorio del proyecto o de la aplicación. En este caso valdría crear un archivo llamado «hello.htm» (es el que se usa en la función <code>hello</code>) en el directorio «templates» de la aplicación «hello_app».</p>
<pre class="brush:html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"&gt;

&lt;head&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;
    &lt;title&gt;{{ hello_msg }}&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;p&gt;{{ hello_msg }}&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Esta es una plantilla muy sencilla, el lenguaje de las plantillas de django permite realizar muchas más cosas, como herencia entre plantillas, definir bloques, bucles, &#8230;</p>
<h4>Definiendo una dirección para la vista</h4>
<p>Una vez creada la vista y su plantilla, habrá que definir una dirección para poder acceder a la vista. Como se mencionó al principio, para eso está el archivo «urls.py» del proyecto. Este archivo contiene una lista de direcciones a las que se les asignará unas vistas, de modo que cuando se abra esa dirección la vista asignada se encargue de crear su correspondiente página web.</p>
<p>En este caso, el archivo «urls.py» quedaría del siguiente modo:</p>
<pre class="brush:python"># urls.py
# -*- coding: utf-8 -*-
# Django URL patterns for hello world project.

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'', 'hello_world.hello_app.views.hello'),
)</pre>
<p>Como se puede ver, lo único que se hace es añadir un patrón (una expresión regular) con una vista asociada. En este caso se trata de una dirección vacía (<code>r''</code>), la raíz del dominio, a la que se asocia la función <code>hello</code> que se definió en las vistas de la aplicación.</p>
<h4>Probando la aplicación web</h4>
<p>Una vez llegado a este punto, ya se puede probar la aplicación web, para ello no hace falta tener ningún servidor web instalado, ya que django dispone de uno para realizar pruebas. Para ejecutarlo, desde el directorio del proyecto:</p>
<pre>$ python manage.py runserver</pre>
<p>Y aquí concluye esta introducción básica, pero larga, próximamente más. Si os ha gustado y queréis ir aprendiendo por vuestra cuenta, siempre podéis leer <a href="http://docs.djangoproject.com/en/dev/">la documentación oficial de django</a>.</p>
<img src="http://feeds.feedburner.com/~r/4BitsBlog/~4/iJjihhoGY74" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/primeros-pasos-con-django/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
