jueves, 16 de julio de 2015

Hashes: md5sum, sha256sum, sha512sum, etc, con semilla, desde la consola


Los hashes checksum se han vuelto muy populares para validar la integridad de los archivos que descargamos por Internet. Sobre todo por ejemplo para las diferentes distribuciones de Linux.

Sin embargo la seguridad de esos hashes ha sido cuestionada, es cuestionable o al menos deja ciertas dudas. Dado que simplemente es un hash si existe algún archivo que lo tenga, existirán infinitos archivos que tendrían ese mismo hash. De hecho es posible, al menos en teoria, descargar una iso de alguna distribución linux con un determinado hash, modificarla a nuestro gusto, insertarle por ejemplo algún rootkit y luego agregarle unos bytes adicionales que nos de el mismo hash que el archivo original. Dado que se asume que los valores de la función hash están uniformemente distribuidos (eso seria lo más lógico) la cadena de bytes que habría que agregarle no debería ser mayor a los numeros de bytes que componen el hash.

De hecho seria teoricamente posible que descargar una iso de Linux y modificar su código sin aumentar su tamaño y cambiar ciertos bytes basura (que no se usen o sean invisibles para el usuario) de manera que el código modificado nos de el mismo hash.

Uno podría creer todavía que existe una brecha práctica para hacer estos crack de hash al menos para los algoritmos más populares: md5, sha1, etc. En la actualidad es difícil permitirse ser tan ignorante. Desde el año 2004 se han descubierto brechas en esos algoritmos [1], que generarían hashes idénticos con un poder de computo muy inferior para el que se asumió que fueron generados los hashes [2].

Otro problema con los hashes md5 es que en el caso de tener un rootkit instalado en el kernel este puede alterar el código de un archivo dado y generar como salida el hash md5 original del código original cuando ejecutemos la utilidad destinada por el sistema operativo para ello.

Se me ha ocurrido sin embargo una forma de hacer mucho más dificil la vulneración por medio de ambos métodos. Se basa en la idea de tener más de un hash para un archivo sin utilizar más de un algoritmo.

Es muy sencillo. Se escribe en un archivo una cadena arbitraria que servira a manera de clave para nuestro hash. Luego se concatena dicha cadena con el archivo al cual se le quiere generar el hash  y finalmente se hace calcula del hash con el algoritmo o la utilida destinada para ello.

Lo bueno de la consola de linux es que la concatenación de los archivos puede hacerse al vuelo (on the fly) y no se requiere para nada modificar el archivo original. Esto con la función cat. Si usaremos MD5, los comandos en la consola podrían ser como se vera a continuación:

$ cat archivo_a_generar_hash archivo_clave | md5sum

De esta forma para distintas claves se tendrá un distinto hash. ¿Por qué es tan ingenioso esto?. Porque hasta ahora la metodología es publicar un hash por archivo, en cambio de esta forma podría publicarse más de un hash para un archivo con una clave distinta por hash. De hecho el servidor desde el que descarguemos el archivo podría generar una clave aleatoria cada cierto tiempo con un distinto hash, de forma tal que no se sobrecargue generando los hash. De esta forma se podría verificar la integridad de un archivo para más de un hash. Lo que nos daria una seguridad  casi infinitamente mucho más alta de la que tenemos al descargar un archivo de la forma en como lo hacemos actualmente. Un rootkit, por ejemplo tendría que que estar conectado online exactamente en la sesion tcp que conectemos al momento para saber el hash que consultamos. Simplemente no seria viable, tendría que mantener una copia exacta del archivo para mantener la consistencia con los hash generados. Si el archivo es muy extenso podría notarse que decrementa mucho más de lo que debería el tamaño del disco duro, así que el rootkit también tendría que disimular esto. Esto sin duda haría más difícil su trabajo.  

Esto desde luego no es algo nuevo. Es lo que se usa en el archivo de claves de /etc/shadow para que claves iguales tengan hashes distintos de forma que viendo el shadow no se sepa que son iguales, para ello se le agrega varios bytes que se conocen como salt o semilla. Es sorprendente que los utilidades de hash que vienen con Linux o que se pueden descargar no hayan tomado en cuenta en su línea de comando este sencilllo y elemental caso de uso.

De momento este método podría servirnos para generar nuestros propias hashs ... por si acaso.


Referencias:

[1] http://merlot.usc.edu/csac-f06/papers/Wang05a.pdf

[2] MD5: vulnerabilidades y evoluciones (y II)

martes, 2 de junio de 2015

Los teoremas de incompletitud de Godel y la Inteligencia Artificial


Esta es probablemente una de las entradas más extrañas que escriba dado que no domino con toda la maestria necesaria los temas que pretendo confrontar: los famosos teoremas de Godel y la IA dura. Agradecería inmensamente la notificación de cualquier error que pueda haber cometido al tratar sobre unos temas tan sutiles y complejos.

Los teoremas de Godel básicamente lo que dicen es que no hay forma de demostrar o construir una teoria aritmética que sea a su vez completa y consistente. Completa quiere decir que esta abarque todos los teoremas posibles y consistente que carezca de contradicciones . ¿Lo habré dicho bien? Que la aritmética no este completa no es ningúna sorpresa, son infinidad de libros los que se escriben sobre ellas y los teoremas que aun se siguen publicando y los problemas que aun están pendiente. Pero que se dude de su consistencia debe parecerle bastante raro a cualquiera que haya estudiado como mínimo la matemáticas de bachillerato. ¿No dejo bastante claro que la aritmética no tenía contradicciones?. Esto es apenas una muestra del abismo que hay entre la matemática de los números y la matemáticas abstractas.

¿Es que de verdad hay contradicciones en la aritmética? Ciertamente no las hay en la aritmética que se ve en bachillerato, tampoco en la aritmética en su totalidad. Según algunos matématicos es simple: se ha construido para que para que carezca de contradicciones, para otros se trata de la trascendencia de la verdad. Pero ahora veamos lo que dice la Paradoja de Richard, propuesta por el matématico francés Jules Richard en 1905.

La construcción de la paradoja se basa en asignar un número entero a cada propiedad de los enteros (que es el conjunto de los números aritméticos 1, 2, 3, 4, ....).  La paradoja no describe exactamente cómo hacerlo para un idioma en particular ni mucho menos para todos los idomas. Simplemente supone que es posible hacerlo. Y  parece completamente razonable: dado el conjunto de todas las definiciones de las propiedades de los enteros estas indudablemente tendrán un orden lexicográfico y por tanto seria posible asignarles un número. De hecho computacionalmente hablando es posible asignarle un número entero a cualquier texto para un idioma en específico, escrito siguiendo cierto formato estricto y codificado en bits. Ese número sera único para ese texto en específico, es decir no habrá otro texto que puede tener un idéntico número.  Pero hay un abismo de distancia entre esto y lo que suponía Richard, una de las dificultades es  la posibilidad de expresar de muy distintas formas en un mismo idioma las propiedades de los enteros. Por ejemplo: la propiedad de los números primos se puede expresar como: "son aquellos números que únicamentes son divisibles por ellos mismos o la unidad", o de esta forma: "son los números que no tienen divisores exceptuando el 1 y su propia cantidad".  Pero dejemos esto de lado y vayamos a la sustancia medular de la paradoja de Richard.

Si cada definición corresponde a un entero puede ocurrir que el número asignado a una propiedad también posea la propiedad que indica la definición. Es algo parecido a lo que ocurre cuando decimos la palabra "palabra" es una palabra. Por ejemplo si la propiedad de "número primo" corresponde al número 23 evidentemente ese número tiene esa propiedad. Desde luego la mayor parte de los números no estarán correlacionados con la propiedad que describen, pero aun así puede que haber infinidad de propiedades correlacionadas con sus números. Notése que algunas propiedades pueden ser triviales como la de "los números divisibles por 3",  luego no debería ser difícil intuir que hay infinitas propiedades tantas como números naturales . Basándonos en estas observaciones se puede definir la propiedad de ser "richardiano" como la de "aquellos números enteros que no están correlacionados con la propiedad que describe su definición". Pero al hacer ese enunciado este necesaria y fatalmente tendrá que estar númerado por algún preciso, determinado y único número entero.  Luego surge la pregunta de la correlación del enunciado con el número que lo identifica ¿es richardiano ese número?. Según nuestra definición el número será richardiano si y solo si no esta correlacionado con su propiedad. Pero como bien sabemos si posee la propiedad de ser richardiano. Por tanto sera richardiano si no posee la propiedad de ser richardiano. Sera richardiano si no es richardiano. De hecho el "sera" es artificial, se trata de que es richardiano si no es richardiano. Una contradicción completa y redonda y absolutamente inesperada. ¿Cómo fue posible que nos extraviaramos así?!!!.

Ahora el razonamiento de Richard formalmente hablando es una falacia. El errror esta en las premisas de las cuales partimos, suponer que se pueden númerar las propiedades de los números enteros empleando el lenguaje natural, cuyas dificultades observamos,  y no hacer ninguna diferenciación entre lenguaje y metalenguaje matemático ¿es esto un alivio?. La demostración de Godel, posterior a esta falacia, de hecho utiliza una construcción parecida a la construcción de Richard pero todavía más compleja, precisa, aguda y certeramente ingeniosa. Lo que Godel númera no son las propiedades de los números enteros, son las propias demostraciones aritméticas, es decir su propia columna vertebral, a esos números se les llama números de Godel. Aun tratándose de demostraciones triviales son astronómicos.

Godel logró llegar a una contradicción de autoreferencia como la que se construyó en la paradoja de Richard, reflejando el metalenguaje matématico en su númeración y lo hizo utilizando una lógica formal, nada de lenguaje natural. Lo que logró demotrar como se dijo al inicio es que la aritmética si es consistente no es completa (1er teorema), si es consistente entonces no puede demostrar su propia consistencia (2do teorema).

Esto tuvo importantes consecuencia en el mundo de la computación.  Las primeras de esas consecuencias fue la indecibilidad del problema de parada de Turing. Pero la resonancia más tremenda del trabajo del Godel ha sido en el campo de la IA dura y el trabajo que tal vez más se ha hecho eco de esto ha sigo el libro "La Nueva Mente del Emperador" de Roger Penrose.

La IA lo que postula es que la inteligencia humana es algoritmica y por tanto simulable y mejorable mendiante el computador. Muchos intuyen y otros creen que los teoremas de Godel refutan semejante aseveración. El razonamiento parece ser el siguiente:

  • Si la inteligencia humana es algorítmica entonces la aritmética también lo es.
  • Si la aritmética es algorítmica entonces hay una teoria completa y consistente de la misma: el propio algoritmo que hace aritmética seria esa teoria.
 Pero:
  • No hay una teoria completa y consistente de la aritmetica (demostrado por los teoremas de Godel)
  • Por tanto la aritmética no es algorítmica
  • Luego la inteligencia humana tampoco es algorítmica. 

Todo ese mundo fantástico y platónico de las matématicas, no simplemente lo hemos creado, así lo cree Roger Penrose: lo hemos visto. La mente humana posee una facultades y una propiedades aun insospechadas para ella misma, Roger Penrose, intuye unas leyes físicas no descubiertas que la rigen.  El problema con las máquinas, con las computadoras que tenemos actualmente, es que son esencialmente ciegas.

Los teoremas de Godel, aunque muchos aun todavía no se hayan percatado del todo, parecerían poner el a la IA dura al mismo nivel al que fueron relegada la física que buscaba el movimiento perpetúo en siglos pasados.  ¿Será ese realmente el destino de la IA dura? El movimiento continuo era, para algunos, al igual como la sentencia indecidible de Godel, algo así como una serpiente que se muerde la cola, quiero decir que se basaba en suponer la existencia de un movimiento que se retroalimentara asi mismo demanera que nunca se detuviese, permitiendo generar una energía constante en el tiempo, contradicciendo el principo de conservación de la energía.

Pero en lo personal no veo así de claro la decandencia de la IA dura. Lo cierto es que si ha dado muchos resultados, llevándole en eso una gran ventaja a los físicos que buscaban la quimera del movimiento perpetúo. Máquinas que juegan el ajedrez mejor que un campeón mundial, que reconocen imágenes y rostros, que reconcen las voz humana .... No estoy en contra de la idea de la IA dura, reconozco sus logros y los aprecio, deseo que esos avances continúen .... incluso hasta me atrevería a investigar a ver si doy también con algo (RISAS).  Pero la gente que desea ser como una máquina o convertirse en un robot o unos bits inmortales ciberespaciales, como Kurzweil, quienes creen que el hombre quedara obsoleto, esa clase de ciberpunk y  transhumanos, simplemente me abruman. A duras penas puedo comprender semejante anhelo. En primer lugar porque aunque me entusiasme la IA dura soy muy escéptico en cuanto a que las computadoras puedan superar la inteligencia humana.  En segundo lugar porque aun asumiendo que lo lograsen, no me parece tentador transformarme en una de ellas. Me parece hasta cierto punto que es como renunciar por completo a asumir o descubrir el propósito de la vida humana. ¿Cuál propósito?. Solo lo intuyó, ¿es gracias al espíritu o es estupidez?.

Me he alejado del titulo de la entrada pero creo que era necesario.

Referencias:

[1] Jeff Makey.  "Gödel's Incompleteness Theorem is Not an Obstacle to Artificial Intelligence".

martes, 26 de mayo de 2015

Mark V Shaney: Trolleando a lo Grande


No soy para nada amigo de los trolls, aunque he sido víctima de ese epiteto en algunos foros debido a lo obsesivo que puedo hacer en algunas cosas  ... y a lo abusivas que pueden ser algunas personas con eso de calificar de trolls a los demás.

En la vieje Usenet a alguien se le ocurrio crear un programa que generara textos aleatorios utilizando un truco basado en las cadenas de Markov. Ese programa se hacía pasar por un usuario de nombre Mark V Shaney, el programa tuvo cierto éxito, al parecer alguna personas pensaron que se trataba de un tipo extravagante. El funcionamiento del programa en realidad es muy sencillo y no hay que entender del todo el concepto matemático de las cadenas de Markov para comprenderlo.  Se basa en tomar uno o muchos textos y crear una base de datos de la palabra que sigue a un grupo de palabras tomandolas en número fijo de 2 o más . Luego a partir de esa data se generan oraciones aleatorias basandose en la precedencia de la palabra. Por ejemplo, si se va a crear una base de datos de las palabras que siguen a un grupo de palabras de 2, y para el caso de "iba al" hay se encontraron 6 palabras que seguian a esas dos: parque, parque, estadio, campo, paraiso, paraiso, entonces en la oración generada con el grupo de palabras de "iba al" , habrá la posibilidad 2/6 de que la siguiente palabra que siga sea "parque" o "paraiso" (esas palabras se repitieron 2 veces) y 1/6 de que la que siga sea "estadio" o "campo".  Luego que se ha generado la oracion de tres palabras se toman las dos ultimas palabras y se genera, repitiendo el mismo proceso anterior, una nueva palabra, y así hasta tener un texto completo o de tantas palabras como se quiera. ¿Y cómo hacer con los signos de puntuación, el '.', la ',', ':', etc. Simple, se toman las palabras con los signos de puntuación, como si fuera una palabra más. Es decir que al final tendremos un texto con signos de puntuación y todo.

Lo fantástico es que en no pocos casos las oraciones pareceran tener sentido y se dejará al juicio del lector pensar si lo escrito es un sin sentido o un enigma. Hay gente que tiene una enorme grado de tolerancia a la ubicuidad y al caos literario, asi que la posibilidad de que el programa se gane la empatía de algunos cuantos no es poca. De hecho lo más impresionante es que si el programa funciona para algún idioma alfabético podría funcionar perfectamente para cualquier otro. Incluso estoy casí seguro que funcionaría en chino.

Me estaba planteando si hacía o no un programa tipo Mak V Shanney cuando me topé con el código de Timothy Musson un tipo interesante.  El programa lo escribio en lenguaje C  y es muy sencillo de utilizar, se maneja desde la consola de Linux. Básicamente el programa toma un conjunto de archivos cuyos nombres se le pasan como argumento a través de la consola y con ellos genera un texto aleatorio. Tiene un parámeto denomidonado "depth" que viene hacer el número fijo de palabras precedentes a partir de la cual se generara la palabra siguiente, por defecto utiliza el valor de 2. Es bastante claro que a menor profundidad el numero de textos generados puede ser mayor y por tanto el texto resultante es más ubicuo, quiero decir caótico, mientras que a mayor profundidad el número de textos generados es menor y por tanto el texto resultante es menos ubicuo, de hecho se dara el caso de que obtendremos uno de los los textos originales pasada una profundidad mínima. Por ejemplo, aunque el número de textos que le pasemos sea muy grande, con un 8 de profundidad será muy probable que obtengamos uno de los textos originales, siempre y cuando nos refiramos a textos normale y corrientos (extratos de novelas, ensayos, articulos periodisticos, etc).

Decidí pues experimentar con el programa de Timothy Musson y me busque un foro con un alto grado de ubicuidad. Encontrandome con decondicionamiento.org, me metí en uno de los hilos más disparatados que conseguí.  Tome todos los textos que pude, copiando y pegando, y me puse a jugar. El resultado fue el siguiente:

Fijaos en lo que pasa en zona de caos?. Vamos, ni que hubiera empezado el foro parecería que se va a hablar de supercosastochísimas que parecen una peli de Harry Potter o fantocherias x el estilo... para eso está Ekiria jajaja Twisted Evil Laughing También es importante destapar la propaganda política de un vil ataque de hemorroides espirituales, pues se acusa a decond de desprestigiar a ZDC y decond tiene una orientación más amplia desde un principio de tal modo que permita que la ciencia y los resultado objetivos y la magia del caos, te haces un sigilo y eres el puto amo. a veces como con Laynd, es como el tao pero mas punk. esas son las reglas del buen caota.a mi no me ofende que me suena bien así. En esa dirección a la Magia del Caos en los bares pero os aseguro que no me suelo leer nada de lo real" de tal forma que los que pasamos de la magia(k) puede ser un rito de paso. En mi caso lo unico que he pactado con Luscious es la propia realidad lo deseará el discipulo), pero si así lo hace el "discípulo" estará asumiendo una dinámica dictada por el trolleo y bronquismo constante. Más adelante, fue un poco en suspenso la forma en que tono me dices esto ANLALA, porque se que tu me miras con cierto recelo por mis subidones, pero vamos... que la habilidad se desarrolle sóla, pero el tipo habia amenazado con denunciar a la ciencia y la repetición en el inconciente; quizás no has contemplado todas las posibilidades pero no a corto plazo pq no tengo tiempo) sería programar algún sistema con el universo estaba hecho de Leyes inmutables a la Pasionaria. Sin vosotros no hubiera podido. Gracias> Y que no te has tomado nada) y es una falta de decencia, oyes ... seDADA,

No puse el texto completo, es muy largo. Luego se me ocurrio mezclar los comentarios del foro con otro de conspiranaia y el texto de "La precesión de los simulacros", de Baudrillard, todo un clásico, uno de los resultados que obtuve fue este (tampoco pongo el texto completo):

Fijaos en lo que le buscamos la coherencia a los de El Monasterio, ¿cómo nos va a ser una apariencia y pertenece al orden de la negación radical del signo como reversión y eliminación de toda forma simbólica y de la ciencia. Supongo que por algún motivo no resulte aceptado por el otro, una autoridad por así decirlo y que malmetio durante muchisimos meses (en los que pudiera tener ahora entre foros son cosecha del pajillero de kabala777 (tambien alias francisco). O es que por ahí(léase Zdc) utilizan la magia intenta responder al "¿qué?". añadiría la cuestión es más que a la vez se hunde en su for­ma pura, la desmuseificación es una buena apariencia y pertenece al orden del sacramento. En el tiempo a confundirse con el lado irracional de la apariencia, sino al
 de la negación radical del signo como valor, parte del foro ni le interese siquiera necesariamente el rollo sadomaso, determinar de antemano los papeles, límites, etc a los locos, etc.), ni cuando la Unión Soviética intervino en Afganistán. La familia Bin Laden ya trabajó para la práctica es entre otras cosas el desarrollo de un museo. El pánico invade de pronto a occidente ante la posibilidad de escapar a la gruta auténtica y después se visita la reproducción). Es posible que la peña venga a leer un articulo sobre el asunto, sino que has "creído" que iba a funcionar, has dado ese paso mental, ese salto al abismo(tampoco es para tanto) que significa que no se si me explico. ..bueno se me ha mandado foto esas kosas hay ke kurrárselas más hombre jajaj Si, May
hem, hay santo y seña. La palabra es: "Abrahadabra". Muy interesante todo esto de evitar las fantocherías y demás tontadas pueda servir para que la ciencia no pueda más que sus efectos no se equivoca: en este sentido, todos los indios por parte de lo real y lo que se supone que debería.


¿Interesante? Este programa como dije es muy sencillo, a estas alturas existen programas mucho más sofisticados. Uno de ellos es uno de los links que tengo en el panel derecho del blog. Es un programa que simula escribir articulos cientificos aunque lo que dice  no tiene ni pies ni cabeza. Aun así algunos de esos artículos han pasado el visto bueno para publicarse en revistas o dar conferencias, con la expresa intención de ridiculizar al supuestamente muy serio filtro de selección que hay detrás de todo eso. El que inicio esta ola de fraudes académicos fue Alan Sokal con su famoso escándalo,  quien pretendia con ello burlarse y desenmascarar el lenguage pseudo cientifico, pomposo y sin sentido de muchos de los textos y personajes de la postmodernidad.

Hace no mucho leí que uno o algunos de los programas que han participado en el Premio Loegner, se han basado en versiones más o menos sofisticadas de las cadenas de Markov. Minsky ha denunciado dicho premio como un truco publicitario. Sea como sea, para efectos de la postmodernidad pareciera que estos programas han pasado la prueba de Turing.

Recomiendo también leer el texto de "Cómo deconstruirlo casi todo", en inglés, de Chip Morningstar.

domingo, 24 de mayo de 2015

Ver mapa topográfico (con cotas o curvas de nivel) en Google Maps


Supongo que normalmente la forma de ver un mapa topográfico en Google Maps seria hacer lo que dice este video, desgraciadamente a mi no me funciona, de haberlo hecho no me hubiese puesto a escribir esta entrada. 

Por alguna razón en el  google chrome que instale en Trisquel no puedo acceder a las funciones de ver el relieve del mapa. Recuerdo que cuando utilizaba los navegadores tiempo atrás eso no era ningún problema.  ¿Era en Windows o en Linux?. Uso Linux y no he probado eso en Windows, tal vez ni siquiera lo haga o me acuerde de hacerlo.

El caso es que si no puedes ver las cotas de un mapa con google a través de la interfaz gráfica hay parámetros de URL que se le podrían pasar para ver el mapa topográfico con cotas. Por ejemplo, este link muestra un mapa con el pico de Naigutá en el centro y sin relieve:

https://www.google.co.ve/maps/@10.5398457,-66.7780024,14z?hl=es-419

Si se quiere ver el mapa con cotas y relieve basta con quitar el parámetro hl=es-419 y colocar el parámetro "data=!5m1!1e4" de esta forma:

https://www.google.co.ve/maps/@10.5398457,-66.7780024,14z/data=!5m1!1e4 

En este link se explica como utilizar los parámetros de URL de google chrome utilizando la sintaxis vieja, aunque recomendaría comenzar por los comentarios de stack overflow.  La nueva sintaxis, la que utilice en el ejemplo, tiene también una explicación aunque mucho menos exhaustiva en el mismo site.

Lo que hace google chrome cuanto tipeamos la vieja sintaxis es mapear la a la nueva y redirigir al link. Como se puede comprobar al colocar una dirección como esta:

http://maps.google.com/?ll=40.921555,-3.873539&spn=0.089888,0.181789&t=p&z=13

Me topé con este problema cuando buscaba una forma fácil de identificar todos los picos del Waraira Repano. A ojo por ciento  no es fácil de hacerlo porque hay picos que sobresalen y tapan a otros, los picos se parecen y las perspectivas te impiden apreciar con seguridad cuál es el más alto, todo es mucho más intrincado, la información que tiene que procesar el cerebro es más compleja o al menos así lo veo yo. Creo que con mapa de cotas bidimensional eso es mucho más fácil y ayuda muchisimo a la visión tridimensional, pero no pude culminar el trabajo en las 3 o 4 horas que me propuse y es difícil que consiga otro espacio de tiempo para hacerlo. Lo hacía por puro hobbie.

miércoles, 20 de mayo de 2015

Colocar subtitulos de idioma a un video

Hay muchos videos que se puedes descargar por Internet, pero gran parte están en inglés. Por fortuna hay personas y páginas dedicadas a colocar los subtitulos a esos videos y que los difunden de forma completamente gratuita como la de difunde la palabra.  Estas traducción se almacenan es un archivo en formato de texto con extensión '.srt' . Hay varias formas de colocar los subtitulos a esos videos. Una de las herramientas que se utiliza para ello es mencoder, aunque la línea de comandos para hacerlo es bastante engorrosa y no es fácil de explicar, algo como esto:

$ mencoder -sub archivo_subtiulos.srt -subcp iso-8859-1 -ovc xvid -xvidencopts bitrate=14400 -subfont-text-scale 2.5 -oac pcm -o video_entrada.mp4 video_salidad.mp4

Además de lo difícil que es utilizarlo (la instrucción anterior no vale para todos los casos) mencoder es sumamente lento para colocar los subtitulos. No se recomienda utilizar esa herramienta, que parece más hecha para propósitos investigativos o académicos que para los propósitos mucho más mundanos de la mayoría de la gente.

El parámetro iso-8859-1 es la fuente en la que esta códificado el archivo de texto '.srt' y que es por lo general en la cual se codifican las traducciones que se descargan de la página citada. Para saber con seguridad cuál es la fuente en la que esta codificado el archivo se utiliza el comando file:

$ file nombre_archivo.X

Una forma mucho más sencilla y muchísimo más rápidad de colocar los subtitulos es con mkvmerge, esta es la que se recomienda.

$ mkvmerge -o video_salida.mkv video_entrada.mp4 --sub-charset 0:ISO-8859-1 -s 0 archivo_subtitulos.srt

Luego de traduccir 2 videos con esta instrucción no tuve problemas para ver los subtitulos en ninguno en los reproductores de video de Linux como VLC, ¡Y no tarda más de 5 segundos en comparación con mencoder que puede tardar hasta media hora para traducir un video de hora y media !!!. Pero en el caso de uno de los videos no logré verlo en el televisor digital que poseo en mi casa. Aun desconozco si me falto colocar algo más en los parámetros de la instrucción de arriba para evitar ese inconveniente.  Si lo descubro haré las correcciones pertinentes en esta entrada.


jueves, 30 de abril de 2015

Alternativas Monetarias para Venezuela


Tengo que aclarar que no soy economista, sino informático y este blog hasta ahora ha estado centrado solo en los tópico de mi área específica. Sin embargo crear otro blog para verter las ideas y opiniones que voy a dar aquí es algo que me parece un desperdicio. Tengo otro blog pero es sobre  temas algo más raros y lo publico bajo seudónimo. Hasta ahora no he querido romper ese anonimato. Pero seria complemente errado suponer que los informáticos no estamos en la capacidad de opinar o razonar sobre temas como estos, los requerimientos del mundo actual nos obligan a ser expertos de negocio y el caso del dinero o la moneda no es una excepción como lo demuestra el origen de las actuales criptodivisas.

La otra razón que mi impulsa a escribir esta entrada es la terrible y  insufrible crisis que estamos atravesando los venezolanos,  la muy relativa paz y el silencio atronador con la cual la estamos sobrellevando muchos de nosotros. Asi que de momento voy a salirme de la línea del blog para comentar que alternativas monetarias tendríamos los venezolanos para salir de la crisis.

Nuestro país esta atravesando una crisis financiera. Con crisis financiera se quiere decir que el problema de raíz no es una crisis de escasez de recursos, que no es una crisis humanitaria sino básicamente una crisis del flujo del dinero y la entrada del dinero, los problemas derivan de eso.  Hay escasez de dólares, una alta demanda del mismo y una baja oferta de esa codiciada moneda, por otra parte los únicos que compran bolívares son los colombianos. Esta escasez de dólares es causada por el control monetario y la fuga de divisas.

Debemos entender que una moneda es un producto y que como tal esta sujeta a las leyes de la oferta y la demanda. Esto puede sonar extraño a algunos, pero no lo es. Una moneda es un producto basado en la confianza y la solidez del estado que la emite. El estado además le da un uso obligatorio a la moneda y hace necesaria su circulación con tan solo tasar sus tributos en la misma.

Básicamente el dólar sube porque hay una alta demanda del mismo y hay una alta demanda de dólares debido a la gran cantidad de importaciones que tiene el país. Nada más en lo que comemos se importa el 70%. El país importa, pero no produce. El flujo de dólares entrante proviene de las exportaciones de un recurso no renovable al cual la naturaleza le tomo millones de años producir, mientras que el hombre lo consumirá en apenas un par de siglos: el petróleo.

El problema de raíz de Venezuela es en realidad que no produce. Importa alimentos, vehiculos de transporte terrestre y aéreo, electrodomésticos, maquinaria pesada, repuestos para maquinaria, etc, todo, casi todo. Somos grandes consumistas y para seguir importando necesitamos dólares.  De allí la escasez de la divisa.

La escasez de dólares provoca la depreciación monetaria del bolívar y la escasez de los productos que importamos de forma directa o la escasez inducida por el cierre de las fábricas nacionales que a su vez dependen de los dólares para la compra de repuestos o insumos. 

El dólar se encarece y nuestra moneda cada vez vale menos hasta que llegamos al punto de cuestionarnos si realmente sigue teniendo sentido sequir usándola.

Además la depreciación monetara aupada al control cambiario y al control de precios trae aparejada una seria de distorsiones que en la actualidad son el flagelo de la economía venezolana:

  • El contrabando: se obtiene una altisima rentabilidad al llevarse los productos nacionales de forma ilegal, dado que el control de precios pone esto muy por debajo de los equivalentes en dólares en el mercado vecino. Las ganancias son multimillonarias.
  • Bachaqueo: comprar productos regulados por el control de precios para después venderlos más caros. 
  • Mercado negro de dólares: para el caso de Venezuela que es el que tratamos se dice que tiene su principal sede el Cúcuta, Colombia, el país que más se benecia del contrabando con Venezuela y cuya deflación no seria exagerado suponer que se debe en gran parte a la  merma e inflación de la economía venezolana.

Hay pocas alternativas que están sobre la mesa y que se podrían considerar para o bien sustituir la moneda o aumentar la apreciación de la misma. Entre estas alternativas están:

  • Dolarización 
  • Bolivarización del precio del petróleo
  • Moneda electrónica

Dolarización


Es la alternativa de la que más se ha hablado y la que parece más viable y atractiva de todas. Ha sido implementada con éxito en paises como Ecuador.







Bolivarización del precio del petróleo

De quien leí esta propuesta originalmente fue de Jairo Larotta en Aporrea. En su artículo el habla es de bolívares-oro no simplemente de bolívares. La propuesta original de Jairo no la he podido comprender del todo

























miércoles, 29 de abril de 2015

X11 como usuario root o cualquier otro usuario

Muchos de los usuarios de linux se han sentido tentados alguna vez por ejecutar una aplicación gráfica desde la terminal en modo root o cualquier otro usario, pero se han encontrado con algo como esto:

.... cannot open display: :0.0

Si se trata de una aplicación java dira algo así:

java.lang.internalerror can't connect to X11 window server using ' 0.0' as the value of the DISPLAY variable

La forma más fácil de salir de esto seria mediante un: 

$ xhost +si:localuser:nombre_usuario 

También se podría modificar directamente los archivos involucrados en esto, aunque como era de suponer, es más tedioso, lo indico a modo de curiosidad. 

Para permitir que la aplicación se ejecute con el usuario activo en la consola se debe primero ubicar una clave en el directorio /var/run/xauth/ , allí se encuentra un archivo que se puede también conseguir con el comando:

$ find /var/run/xauth/A${DISPLAY}-*|tail -n1

Publicado por KENTNL, de cuyo blog extrage toda esta información . Luego de identificado el archivo (en mi máquina solo es uno), se debe imprimir y decodificar la clave con el comando:

$ sudo xauth -f /var/run/xauth/nombre_archivo  list

Lo cual mostrara algo como esto:

#ffff##:  MIT-MAGIC-COOKIE-1  711f067eae4ec73599dc38dbfaa164f0


Es casi obvio que 711f067eae4ec73599dc38dbfaa164f0 es la clave. Dentro del usuario en el cual queremos tener acceso tipearemos finalmente un comando como este:

$ xauth add :0 MIT-MAGIC-COOKIE-1 711f067eae4ec73599dc38dbfaa164f0

El cual creara un archivo llamado .Xauthority en el directorio home del usuario logueado con las credenciales que le daran finalmente el acceso a X11. Si después se le quiere quitar acceso a X11 basta con borrar ese archivo. Desgraciadamente la clave cambia con cada reinicio de la computadora asi que si se quiere hacer este cambio permanente deben seguirse las recomendaciones del blog de KENTNL.


viernes, 24 de abril de 2015

El Misterio del pase de parámetros en Java: ¿por valor o referencia?


Resulta sorprendente como después de llevar tiempo programando en Java y haber hecho infinidad de maravillas  uno se pueda quedar perplejo y hasta embarazado con la cuestión de si se pasan o no los parámetros por valor o referencia y cómo y cuándo. En un aula de clases no se le suelen dedicar ni dos horas ha hablar sobre eso.  De hecho en la Web existen diversidad opiniones sobre este tema, ¡pero no debería estar sujeto a opinión!, estamos hablando de algo que indiscutiblemente  tiene una implementación formal, de algo que esta programado y definido por el standar de Java por lo siglos de los siglos y que nadie puede cambiar ¿pero de cuál standar estamos hablando? ¿sera uno de estos? ¿o estos? ¿quién sera tan sesudo y paciente como para ponerse a revisarlos?. La polémica esta armada, vean la que se armo en stack overflow por este tema.

Parece que el problema esta en la forma en como hablamos. De hecho creo que eso de parámetros por valor y referencia es semánticamente confuso, pero Scott Stanchfield que es mucho más experto que yo, no esta de acuerdo con mi opinión, ni con la de muchos otros. Hablar de parámetros por valor y referencia no es algo muy típico de java o de los libros que tratan sobre java, no les extrañe si no consiguen nada sobre eso en muchos o no pocos de ellos.  Eso es algo más bien propio de lenguaje C. En java no se declara explicítamente parámetros por referencia o por valor, no existen por ejemplo los punteros , que es de donde viene esa distinción. Y sin embargo los parámetros implicítamente se pasan por valor o por referencia. Así que no es simplemente una extrapolación invalidad de los conocimientos de lenguaje C.

Un tema tan sencillo como este es algo que este link, parece haber cubierto plena y satisfactoriamente.  Lo dice y lo muestra muy claro:

"En Java todos los parámetros se pasan por valor
Cuando se realiza la llamada a un método, los parámetros formales reservan un espacio en memoria y reciben los valores de los parámetros actuales.
Cuando el argumento es de tipo primitivo (int, double, char, boolean, float, short, byte), el paso por valor significa que cuando se invoca al método se reserva un nuevo espacio en memoria para el parámetro formal. El método no puede modificar el parámetro actual.
Cuando el argumento es una referencia a un objeto (por ejemplo, un array o cualquier otro objeto) el paso por valor significa que el método recibe una copia de la dirección de memoria donde se encuentra el objeto. La referencia no puede modificarse pero sí se pueden modificar los contenidos de los objetos durante la ejecución del método"

En primer lugar lo que dice allí hecha por tierra que en Java se pasen parámetros por referencia y valor, dado que dice que solo se pasan por valor, y por tanto si se estaría extrapolando de forma invalidad los conceptos de lenguaje C. Pero antes de discutir eso vamos a ver cómo es que maneja java el pase de los parámetros.

Según ese link si los parámetros son primitivos la función tomará sus valores pero no podrá modificar el valor del parámetro original. Si los parámetros son objetos, la función podrá modificar los contenidos de los objetos.

Pero ¿qué pasa si los parámetros que se le pasan son arrays de primitivos? Efectivamente el link no dice nada sobre eso. Los arrays en Java son objetos aunque sean array de primitivos,  no es algo que sea obvio o haya que deducir (excepto programando), hay que saberlo.  Alguien que comento en Stack overflow dice que eso se especifica claramente en en la sección 4.3.1 de la Java Language Specification

Asi que si escriben:

char bb[] = {'s', 'o', 'p'};
if (bb instanceof Object) System.out.println("Yes!");

dira 'Yes!' .

Así que eso que se decía de que todos las clases de Java heredaban de Object es también cierto para los arrays primitivos.

Eso si, si escriben:

char bb[] = {'s', 'o', 'p'};
System.out.println("Nombre de Clase: " + bb.getClass().getName());

Les saldrá una cosa rara.

El link también decia que si se pasaban objectos a un método el contenido de estos podría ser modificado por el mismo. Por el contenido entiendo los atributos del objeto. Sin embargo hay ciertos objetos que sobrecargan el operador '=' (extrapolando la terminología de C++ dado que en Java en realidad no se sobrecargan los operadores) para lo eso no es cierto. Me refiero al objetos como String o Integer.

Si se hace:

String cadena = 'dsfskjlf';

luego se pasa como parámetro  a un método y allí se sustituye por otro valor eso no tendrá ningún efecto sobre el parámetro que se paso luego de salir del método. Parece que esto es cierto para todo Objecto que sobrecargue (extrapolando como dije antes) al operador '=', los cuales no son muchos.

Formalmente no se como se explicaría estas excepciones en Java, porque en general es cierto que si los atributos de un objeto que se paso como parámetro a un método se modifican en dicho método los cambios se mantendrán luego de salir del método. En el caso de String y Integer parece claro. aunque sea raro, que el valor que se le asiga a los mismos no constituye un atributo del objeto.

Para evitar las extrapolaciones con lenguje C, Java debe tener un lenguage complementamente propio y autosufienciente, en donde los casos que he mencionado anteriormente no induzcan la menor confusión. Sin duda que Java tiene eso, aunque no lo maneje a ese nivel y al parecer son muchos los que tienen ese problema. Quiero decir, por ejemplo, que encuentro incomodo,  referirme a casos como los anteriores sin hablar de parámetros por referencia y valor o referirme a algo como la sobrecarga que como se ha visto no serían terminos muy propios o apropiados para el  lenguaje Java. Incluso seria errado simplemente decir que en Java los parámetros siempre se pasan por valor, allí también se esta extrapolando. ¿Pero no refleja esta confusión también debilidades en el lenguaje Java?.

Concluyo finalmente con un código que de forma empírica muestra como maneja los parámetros Java. Con esto espero no volver a tener nuevamente esta confusión.


package misc;

/**
 * Programa que ilustra el pase de parámetros en Java
 * @author alexander
 */
public class PasoParametrosFunciones {
    public PasoParametrosFunciones () {
        int a=3;
        char c='a';
        byte e= (byte)11;
        System.out.println("Paso de valores primitivos: ");
        System.out.println("Valor antes de ejecutar la función: a = " +a + ", c = " +c + ", d =" + e);
        paso_primitivos (a, c, e );
        System.out.println("Valor despues de ejecutar la funcion: a = " +a + ", c = " +c + ", d =" + e);
       
        int aa[] = {1, 2, 7};
        char bb[] = {'s', 'o', 'p'};
       
        System.out.println("Paso de arrays primitivos: ");       
       
        System.out.println("Valor antes de ejecutar la función: aa[2] = " +aa[2] + ",bb[1] = " + bb[1]);       
        paso_array_primitivos (aa, bb);
        System.out.println("Valor despues de ejecutar la función: aa[2] = " +aa[2] + ",bb[1] = " + bb[1]);               
       
        System.out.println("Paso de Objectos: ");       
       
        String veronica = new String ("Veronica");
        Persona persona = new Persona("Carlos Fuentes", 'M', 21);
        Integer v = 4333;
       
        System.out.println("Valor antes de ejecutar la función: String veronia = " +veronica + ", Entero v " + v +
                ", Nombre Persona = " + persona.getNombre() + ", Edad Persona = " + persona.getEdad());

        paso_objectos (veronica, persona, v);
        System.out.println("Valor antes de ejecutar la función: String veronia = " +veronica + ", Entero v " + v +
                ", Nombre Persona = " + persona.getNombre() + ", Edad Persona = " + persona.getEdad());
   
    }
    static public void main(String args[]) {
        new PasoParametrosFunciones ();
    }
    void paso_primitivos (int a, char c, byte e) {
        a=199; c='3'; e= (byte) 'f';
    }
    void paso_array_primitivos (int aa[], char bb[]) {
        aa[0]= 7;
        aa[1]= 99;
       
        aa[2]= 88;
       
        bb[0]= 'z';
        bb[1] ='b';
        bb[2] = 'i';
    }
    void paso_objectos(String nombre, Persona p, Integer aa) {
        nombre= "Laura";
        p.setNombre("Jaimito");
        p.setEdad(1000);
        aa = 821;
       
    }
}

class Persona {
    private String nombre;
    private char sexo;
    private int edad;
   
    public Persona(String nombre, char sexo, int edad) {
        this.nombre = nombre;
        this.sexo= sexo;
        this.edad = edad;
       
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public char getSexo() {
        return sexo;
    }

    public void setSexo(char sexo) {
        this.sexo = sexo;
    }

    public int getEdad() {
        return edad;
    }

    public void setEdad(int edad) {
        this.edad = edad;
    }
   
}

Ghost Effect con la programación script de GIMP (script-fu)

Para GIMP se pueden hacer scripts que automaticen tareas que se hacen desde la interfaz gráfica. Por ejemplo, el siguiente script esta hecho para correr desde bash. Lo que hace es tomar un conjunto de imágenes que representan una secuencia animada y tomando una imagen como fondo transparenta el conjunto imagenes animadas sobre dicho fondo, creando lo que se conoce como un ghost effect. Las imagenes que se utilizen para ello deberán haberse tomado previamente sin mover la cámara y utilizando una imagen como fondo en un escenario vacio y sin nada animado, que este en la misma posición en la cuál se toman la secuencia de imagenes animadas. De otra forma lo que se obtendra es un revoltijo.

#!/bin/bash
# Script para crear animaciones que trabaja con dos capas
# - Una en la que hay un fondo estático
# - Y otra de la animación la cual se transparenta contra el fondo
# El resultado es aspecto fantasmal de la imagen animada.
# Tanto el fondo estático como la capa animada deben tomarse en la misma posición y sin mover la cámara

{
cat <<EOF
(define (crea-transparencia imagen_fondo imagen_animacion imagen_salidad)
  (let* (
     (image (car (gimp-file-load RUN-NONINTERACTIVE imagen_fondo imagen_fondo)))
     (layer nil)
         (drawable nil)
     )

    (set! layer (car (gimp-file-load-layer RUN-NONINTERACTIVE image imagen_animacion)))
   

    (gimp-image-add-layer image layer 0 )
    (gimp-layer-set-opacity layer 25)
    (set! drawable (car (gimp-image-merge-visible-layers image EXPAND-AS-NECESSARY)))
    (file-jpeg-save RUN-NONINTERACTIVE image drawable imagen_salidad imagen_salidad 1 0 0 0 " " 0 1 0 1)
    (gimp-image-delete image) ; ... o la memoria explotara
    )
  )

(gimp-message-set-handler 1) ; Messages to standard output
EOF

imagen_fondo="../00554/0531.jpg"

for i in ../00554/*.jpg; do
  imagen_salidad=`echo $i | cut -d '/' -f 3`
  echo "(gimp-message \"$i\")"
  echo "(crea-transparencia \"$imagen_fondo\" \"$i\" \"$imagen_salidad\")"
done

echo "(gimp-quit 0)"
} | gimp -i -b -


Este es un ejemplo de un video que desarrolle para un proyecto en la universidad hace un tiempo:


domingo, 8 de marzo de 2015

Programación Gráfica en Linux


Programación a nivel de lenguaje C


Este es un programa sobre el conjunto Mandelbrot  extraido de esta página, que no daba ningún detalle de cómo compilarlo. Para poder compiarlo deben descargarse las librerias de OpenGL y Glut, el paquete de build-essentials y utilizar la instrucción:

$ gcc -o maldenbrot.o maldenbrot.c -lGL -lglut -lm




// Compilar con gcc -o maldenbrot.o maldenbrot.c -lGL -lglut -lm
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>

void set_texture();

typedef struct {unsigned char r, g, b;} rgb_t;
rgb_t **tex = 0;
int gwin;
GLuint texture;
int width, height;
int tex_w, tex_h;
double scale = 1./256;
double cx = -.6, cy = 0;
int color_rotate = 0;
int saturation = 1;
int invert = 0;
int max_iter = 256;

void render()
{
    double    x = (double)width /tex_w,
        y = (double)height/tex_h;

    glClear(GL_COLOR_BUFFER_BIT);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    glBindTexture(GL_TEXTURE_2D, texture);

    glBegin(GL_QUADS);

    glTexCoord2f(0, 0); glVertex2i(0, 0);
    glTexCoord2f(x, 0); glVertex2i(width, 0);
    glTexCoord2f(x, y); glVertex2i(width, height);
    glTexCoord2f(0, y); glVertex2i(0, height);

    glEnd();

    glFlush();
    glFinish();
}

int dump = 1;
void screen_dump()
{
    char fn[100];
    int i;
    sprintf(fn, "screen%03d.ppm", dump++);
    FILE *fp = fopen(fn, "w");
    fprintf(fp, "P6\n%d %d\n255\n", width, height);
    for (i = height - 1; i >= 0; i--)
        fwrite(tex[i], 1, width * 3, fp);
    fclose(fp);
    printf("%s written\n", fn);
}

void keypress(unsigned char key, int x, int y)
{
    switch(key) {
    case 'q':    glFinish();
            glutDestroyWindow(gwin);
            return;
    case 27:    scale = 1./256; cx = -.6; cy = 0; break;

    case 'r':    color_rotate = (color_rotate + 1) % 6;
            break;

    case '>': case '.':
            max_iter += 128;
            if (max_iter > 1 << 15) max_iter = 1 << 15;
            printf("max iter: %d\n", max_iter);
            break;

    case '<': case ',':
            max_iter -= 128;
            if (max_iter < 128) max_iter = 128;
            printf("max iter: %d\n", max_iter);
            break;

    case 'c':    saturation = 1 - saturation;
            break;

    case 's':    screen_dump(); return;
    case 'z':    max_iter = 4096; break;
    case 'x':    max_iter = 128; break;
    case ' ':    invert = !invert;
    }
    set_texture();
}

void hsv_to_rgb(int hue, int min, int max, rgb_t *p)
{
    if (min == max) max = min + 1;
    if (invert) hue = max - (hue - min);
    if (!saturation) {
        p->r = p->g = p->b = 255 * (max - hue) / (max - min);
        return;
    }
    double h = fmod(color_rotate + 1e-4 + 4.0 * (hue - min) / (max - min), 6);
#    define VAL 255
    double c = VAL * saturation;
    double X = c * (1 - fabs(fmod(h, 2) - 1));

    p->r = p->g = p->b = 0;

    switch((int)h) {
    case 0: p->r = c; p->g = X; return;
    case 1:    p->r = X; p->g = c; return;
    case 2: p->g = c; p->b = X; return;
    case 3: p->g = X; p->b = c; return;
    case 4: p->r = X; p->b = c; return;
    default:p->r = c; p->b = X;
    }
}

void calc_mandel()
{
    int i, j, iter, min, max;
    rgb_t *px;
    double x, y, zx, zy, zx2, zy2;
    min = max_iter; max = 0;
    for (i = 0; i < height; i++) {
        px = tex[i];
        y = (i - height/2) * scale + cy;
        for (j = 0; j  < width; j++, px++) {
            x = (j - width/2) * scale + cx;
            iter = 0;

            zx = hypot(x - .25, y);
            if (x < zx - 2 * zx * zx + .25) iter = max_iter;
            if ((x + 1)*(x + 1) + y * y < 1/16) iter = max_iter;

            zx = zy = zx2 = zy2 = 0;
            for (; iter < max_iter && zx2 + zy2 < 4; iter++) {
                zy = 2 * zx * zy + y;
                zx = zx2 - zy2 + x;
                zx2 = zx * zx;
                zy2 = zy * zy;
            }
            if (iter < min) min = iter;
            if (iter > max) max = iter;
            *(unsigned short *)px = iter;
        }
    }

    for (i = 0; i < height; i++)
        for (j = 0, px = tex[i]; j  < width; j++, px++)
            hsv_to_rgb(*(unsigned short*)px, min, max, px);
}

void alloc_tex()
{
    int i, ow = tex_w, oh = tex_h;

    for (tex_w = 1; tex_w < width;  tex_w <<= 1);
    for (tex_h = 1; tex_h < height; tex_h <<= 1);

    if (tex_h != oh || tex_w != ow)
        tex = realloc(tex, tex_h * tex_w * 3 + tex_h * sizeof(rgb_t*));

    for (tex[0] = (rgb_t *)(tex + tex_h), i = 1; i < tex_h; i++)
        tex[i] = tex[i - 1] + tex_w;
}

void set_texture()
{
    alloc_tex();
    calc_mandel();

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, tex_w, tex_h,
        0, GL_RGB, GL_UNSIGNED_BYTE, tex[0]);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    render();
}

void mouseclick(int button, int state, int x, int y)
{
    if (state != GLUT_UP) return;

    cx += (x - width / 2) * scale;
    cy -= (y - height/ 2) * scale;

    switch(button) {
    case GLUT_LEFT_BUTTON: /* zoom in */
        if (scale > fabs(x) * 1e-16 && scale > fabs(y) * 1e-16)
            scale /= 2;
        break;
    case GLUT_RIGHT_BUTTON: /* zoom out */
        scale *= 2;
        break;
    /* any other button recenters */
    }
    set_texture();
}


void resize(int w, int h)
{
    printf("resize %d %d\n", w, h);
    width = w;
    height = h;

    glViewport(0, 0, w, h);
    glOrtho(0, w, 0, h, -1, 1);

    set_texture();
}

void init_gfx(int *c, char **v)
{
    glutInit(c, v);
    glutInitDisplayMode(GLUT_RGB);
    glutInitWindowSize(640, 480);
    glutDisplayFunc(render);

    gwin = glutCreateWindow("Mandelbrot");

    glutKeyboardFunc(keypress);
    glutMouseFunc(mouseclick);
    glutReshapeFunc(resize);
    glGenTextures(1, &texture);
    set_texture();
}

int main(int c, char **v)
{
    init_gfx(&c, v);
    printf("keys:\n\tr: color rotation\n\tc: monochrome\n\ts: screen dump\n\t"
        "<, >: decrease/increase max iteration\n\tq: quit\n\tmouse buttons to zoom\n");

    glutMainLoop();
    return 0;
}

martes, 20 de enero de 2015

Seguridad de una infraestructura de Red


Siguiendo el esquema de capas del modelo OSI se podría hablar de seguridad de la Red a nivel de varias capas, nos enfocaremos en solo en 4 de ellas:

  • Seguridad a nivel de Capa de Enlace (intranet)
  • Seguridad a nivel de Capa de Red (intranet)
  • Seguridad a nivel de Capa de Transporte (LAN o WAN)
  • Seguridad a nivel de Capa de Aplicaciones

En cada una de estas capas existen todo un conjunto de protocolos especificados para trabajar dentro de cada una de ellas. Estos protocolos muchas veces presentan ciertos defectos o vulnerabilidades, inherente a la propia especificación de los mismos o las limitaciones físicas que hay en el mundo real para implementarlos, por ejemplo: el ancho de banda o los recursos de la máquina. Por otra parte están las vulnerabilidades de las aplicaciones que trabajan con dichos protocolos. No hay que confundir las dos cosas, una cosa son los vulnerabilidades de los protocolos y otra la de las aplicaciones. En ocasiones existen tecnologías o configuraciones de red que permiten corregir o apaliar los riesgos de un determinado protocolo, en otras no, o bien los inconvenientes o costos son tales que hacen imposible cualquier implementación. Finalmente están las vulnerabilidades ocasionadas por errores humanos en cuanto a la configuración de un servicio o la infraestructura de red.

Hay protocolos de bajo nivel que suelen ser implementados directamente en el kernel del sistema operativo (por ejemplo ICMP). También hay protocolos se ejecutan en aplicaciones que tienen un nivel de privilegio alto, sea root, administrador o system. Debe tenerse en consideración cuáles son los parámetros de configuración óptimos, cuando eso se puede manipular, que permitirían minimizar los riegos de la infraestructura de red, para los protocolos implementados a nivel de kernel. Por ejemplo la deshabilitación de las respuestas a los mensajes de ping, en el caso de que sea pertinente. También debería tenerse muy en cuenta cuáles son las aplicaciones potencialmente peligrosas que se ejecutan con un alto nivel de privilegio y que medidas se pueden tomar para minimizar los riegos.

La tarea del administrador de red en el caso de las aplicaciones que tienen bugs o errores se reduce simple y llanamente a actualizar dichas aplicaciones con los parches respectivos. Hay aplicaciones y sistemas que se actualizan automáticamente mientras que hay otras que no. También existen vulnerabilidades de Zero-day para las que no existen parches conocidos o para las que hay que buscar parches de 3ra partes, en muchos casos de dudosa confiabilidad. Debe evaluarse si en esos casos conviene o no deshabilitar o sustituir los servicios asociados con esas vulnerabilidades.

Una cuestión importante es cómo identificar mediante la monitorización del tráfico de la Red cualquier ataque o fallo en la misma. Evidentemente esto requiere del uso de sniffers y el dominio de técnicas para usarlos. En cuanto al tráfico, en algunos casos, como los mensajes de broadcast o multicast, es posible identificar un tráfico irregular desde cualquier puerto de un switch o ubicación de red. Hay un tráfico de red que solo es visible dentro de los puertos de un switch, hay un tráfico de Intranet y hay un tráfico de Internet . Hay técnicas de hacking como el ARP Spoofing para visualizar el tráfico de un determinado nodo en un Switch.

El responsable de la seguridad de una red deberá tener presente los riesgos que hay a nivel de las distintas capas de la red, cuáles son los protocolos y aplicaciones trabajando en ellas de forma activa en el IBE y la localización física de los nodos o dispositivos asociados. Las aplicaciones afectadas pueden ser el propio sistema operativo.