Conversión de binario a decimal

El uso de los números binarios es mas importante de lo que mucha gente cree. Se trata del lenguaje que el ordenador entiende, ya que este interpreta diferencias de voltaje como (true o HI) y (false o LO). Cada byte de información está compuesto por ocho dígitos binarios, y a cada cifra o se le llama bit. El número utilizado en el ejemplo, el 10110100, sería un byte, y cada una de sus ocho cifras, un bit. Imaginemos que tenemos el número binario . Al sumarle una unidad, este número binario cambiará a . Sin embargo, si volvemos a añadirle otra unidad, este número en formato binario será el (aumenta la cifra a la izquierda, que era , y la anterior toma el valor mínimo). Sumemos ahora otra unidad y el aspecto del número será (tres en decimal). Y podríamos seguir.

Binario Decimal
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 10
1011 11

 

Esto nos permite establecer un sistema bastante sencillo de conversión del binario al decimal. A partir de ahora, cuando escribamos un número binario, lo haremos con la notación usual, con una "" al final del número (ej.: )

Bien, pero ahora nos falta saber que hay que hacer para convertir un número binario a decimal. Para ello hemos de aplicar la siguiente notación matemática:

Donde es el valor del bit binario en cada iteración, o sea, (false) o (true), y es el número de bits a convertir por ejemplo es un byte por que tiene 8 bits, así que en este caso . Así que, si queremos convertir el número binario de 8 bits a decimal sería de la siguiente forma:

Sumando cada cálculo de bit quedaría:


Y finalmente se escribe:

Contador de palabras de una web, en Python

Una vez me propusieron hacer el siguiente programa: "Un programa que cuente las palabras que aparecen en una web cualquiera y ordenarlas alfabéticamente". En ese momento me pregunté que para qué podría alguien querer algo así, supongo que para darle algún fin estadístico. En un principio pensé hacerlo en Perl, pero por alguna razón me vino a la cabeza BeutifulSoup para Python. Y parece que fue una buena idea. Aquí un pequeño ejemplo que funciona bien.

#!/usr/bin/python
 
import sys, re, string, urllib
# Se requiere el paquete BeautifulSoup
from bs4 import BeautifulSoup
 
# La URL es el primer argumento que recibe el programa.
url = sys.argv[1]
 
# Conversion de codigo HTML a texto plano.
texto = BeautifulSoup(urllib.urlopen(url)).get_text()

# Remplazo todos los caracteres ASCII de puntuacion por espacios e inicializa el Array
palabrasArray = re.sub('[%s]' % re.escape(string.punctuation), ' ', texto).split()
 
# Ordenacion sin repeticion de todos los elementos del Array
numero = 0
for i in sorted(set(palabrasArray)):
    # Imprime solo las palabras con caracteres alfabeticos.
    if (i.isalpha() == True):
        numero += 1
        print("%.3d %s" % (numero, i))

Un ejemplo de uso sería:

python contadorDePalabras.py http://www.gnu.org/

Y tiene una salida como esta:

001 About
002 Access
003 Action
004 Add
005 Allan
006 Also
007 America
008 April
009 Art
010 Attribution
011 BY
012 C
013 CC
014 Call
015 Can
016 Canada
017 Christopher
018 Chrome
019 Claim
020 Common
021 Commons
...

Seguro que se puede hacer mejor y mas profesional, pero así de primeras cumple su función.

Reflexión sobre Bitcoin y su uso

Que levante la mano el que sea un experto en Bitcoin. Como bien dijo una vez un amigo "voy a dar mi opinión como experto de barra de bar" sobre el Bitcoin y su uso. Si has llegado hasta aquí y estás leyendo esto es por que no te pilla de nuevas, por lo tanto no voy a explicar lo que es desde el origen de los tiempos.

El otro día hablando con algunos compañeros, una persona mostró interés por el Bitcoin, decía algo así como "he leído por ahí que es una moneda en la que cualquiera puede invertir como en la bolsa, y que su precio fluctúa tanto que puede llegar a doblar su precio fácilmente, con lo cual te puedes forrar". Alguno ya estará sonriendo, ¿a que si?

Al final lo que cuentan son las intenciones, y parece que siempre hay alguien que está buscando alguna opción para sacar el mayor beneficio posible con la menor inversión posible. Y si puede ser, sin riesgos, por favor. Desde el punto de vista del que escribe, estas intenciones son perjudiciales para la comunidad, pero sobre todo para uno mismo. Los sistemas de producción capitalistas  funcionan (y terminan) siempre igual, cuidado. El Bitcoin no se creó para esto, no se ideó para ganar dinero, aunque algunos pocos hicieran mucho dinero en los tiempos de MtGox, a costa de otros pobres desgraciados que ante el pánico de perder todo malvendieron corriendo lo que pudieron. Ese no es el camino.

Las cosas hay que explicarlas sencillas, sin demasiados tecnicismos y sin necesidad de pavonearse con un exceso de intelecto tecnológico. Hay que hacerse entender y llegara todo el mundo. Cuántas veces habré hablado esto con mi amigo John Doe, "¿Te imaginas explicarle a mi madre cómo crear un monedero, cómo cifrarlo, cómo exportar la semilla encriptada a varios dispositivos offline, cómo importarlos en caso de pérdida y cómo cambiar la clave pública/privada cada cierto tiempo?", y eso sin contar con el entendimiento de lo que es una cadena de bloques y qué seguridad tiene o deja de tener. Señoras y señores, la finalidad no es otra que tener una independencia económica, descentralizada, fácil, rápida, barata y segura, y ya de paso escapar del control de gobiernos, bancos y otras siniestras entidades que no paran de imprimir billetes dándole a un botón. El Bitcoin aún tiene que madurar un poco más, se tiene que facilitar su adquisición y que cualquiera pueda tener un monedero de Bitcoin seguro.

¿Sería buena idea que los bancos gestionaran la apertura de un monedero y las operaciones de BTC como si de una cuenta corriente se tratara?

Sería mas fácil ir al banco y decir "Buenos días, quisiera tener un monedero Bitcoin y comprar 2,5 BTC" o "Por favor, quisiera transferir 0,27 BTC a esta dirección", y en menos de 30 segundos... Si algo sale mal quizás se harían responsables, y al fin y al cabo se encargarían de toda la logística "informática" para que el usuario sin conocimientos tecnológicos pueda acceder al Bitcoin. Suena bien, pero al final el banco terminaría de un modo u otro registrando todo en sus bases de datos y harían eso que tanto les gusta hacer. ¿Que hacemos entonces?

Lo bueno es que nadie podría darle al botón de imprimir más Bitcoins, práctica muy habitual en casi todos los países con una grandísima devaluación de su moneda.

Imaginemos una sociedad en la que todo el mundo entiende de criptografía, ciberseguridad y todo el mundo tiene habilidad con los ordenadores. Es mucho soñar a corto plazo. Estamos en ello, y parece que vamos por el buen camino. Lo vital es que la gente tenga confianza; más que en este sistema monetario, en su filosofía inicial, y no pensar en aprovecharse de las circunstancias para enriquecerse, por que eso no suele funcionar, y por que no es un buen camino para llegar al objetivo inicial de todo esto. Como todo, es cultural, es una cuestión de educación de cada uno.

Login en un programa hecho en C

Imagina que tienes un programa hecho en C que sirve para desencriptar passwords. Ahora imagina que no quieres que lo utilice nadie mas que aquellos usuarios que sepan una password. Muchos pensarán que con asignar al binario unos permisos chmod y chown adecuados sería suficiente. Nunca es suficiente. Por ello, hoy voy a explicar una manera de añadir a nuestro programa un simple sistema de autenticación que funciona bien. Este es el código de mi archivo fuente softwareConLogin.c:

/* Compilacion:	gcc -std=gnu99 -Wall -c -MMD -MP -MF"softwareConLogin.d" -MT"softwareConLogin.d" -o "softwareConLogin.o" softwareConLogin.c
 * 		gcc -o softwareConLogin softwareConLogin.o -lcrypt
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <crypt.h>
 
int main(void) {
	const char * const pass = "$1$Fw1PJ/2K$KhVip8FBuJMNXpZh.XqGX.";
	char *result;
	int ok;
 
	result = crypt(getpass("Password: "), pass);
	ok = strcmp(result, pass) == 0;
 
	puts(ok ? "Correcto!" : "Password erronea");
	return ok ? 0 : 1;
}

En este programa de ejemplo he utilizado una librería llamada crypt.h (cortesía de la FSF) por lo que tendremos que especificarlo a la hora de compilarlo con el flag -lcrypt.

Fijaos bien en la siguiente línea:

const char * const pass = "$1$Fw1PJ/2K$KhVip8FBuJMNXpZh.XqGX.";

Esa es nuestra password encriptada. ¿Podríamos ponerla en claro?, si pero cualquiera que tenga acceso al código fuente o a un buen decompilador podría ver cual es nuestra password, y eso no nos interesa. Lo que he hecho ha sido meter en el código fuente la password ya encriptada mediante un método de encriptación MD5/DES que ya expliqué otro el otro día. De este modo, al ejecutar nuestro software lo primero que nos va a pedir es una Password, y si se introduce correctamente el programa continuará, de lo contrario, dará un error de autenticación y finalizará. Se puede mejorar mucho, por ejemplo, añadiendo número de intentos, un usuario además de la password (también encriptado), etc. En unos días pondré una versión mejorada con todo esto y mas.

Encriptar cadenas con MD5/DES en C

Voy a explicar un simple ejemplo de programa en C para encriptar cadenas que se podrán usar a posteriori para securizar el uso de nuestros programas una vez compilados. Es muy sencillo y es una práctica que todos deberíamos ir adquiriendo, y en los tiempos que corren mas que nunca. Para ello he creado un archivo fuente encriptaCadena.c con el siguiente código:

/* Compilacion:	gcc -std=gnu99 -Wall -c -MMD -MP -MF"encriptaCadena.d" -MT"encriptaCadena.d" -o "encriptaCadena.o" encriptaCadena.c
 * 		gcc -o encriptaCadena encriptaCadena.o -lcrypt
 */

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <crypt.h>
 
int main(void) {
	unsigned long seed[2];
	char salt[] = "$1$3xe26505";
	const char * const seedchars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	char *cadena;
	int i;
 
	seed[0] = time(NULL);
	seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
 
	for (i = 0; i < 8; i++) {
		salt[3 + i] = seedchars[(seed[i / 5] >> (i % 5) * 6) & 0x3f];
	}
 
	cadena= crypt(getpass("Cadena: "), salt);
 
	puts(cadena);
	return 0;
}

He utilizado una librería llamada crypt.h (cortesía de la FSF) por lo que tendremos que especificarlo a la hora de compilarlo con el flag -lcrypt. Una vez compilado lo podemos usar de la siguiente manera (ejemplo en un sistema GNU/Linux o Unix):

./encriptaCadena HolaQueTal
$1$Fw1PJ/2K$KhVip8FBuJMNXpZh.XqGX.

Como se puede ver, la ejecución del programa devuelve una cadena encriptada $1$Fw1PJ/2K$KhVip8FBuJMNXpZh.XqGX. que podremos utilizar para validar una password de autenticación en otro programa que pida un Login. Esto es Free Software, compártelo.