Saltar ó contido principal

Suma y resta en Tubes [ desvarío ]

Por si alguien se pensaba que el intérprete_de_Tubes iba en broma (la elección del día quizá no fue la mejor xD), aquí va una pequeña calculadora (suma y resta módulo 4) [ http://pastebin.com/qrU4wWMT ]

Saludos

PyIC ( Librería IRC para python ) 0.2

Pues eso, habemus nueva versión de PyIC ( una librería para clientes IRC ), ya está subida en GitHub [ https://github.com/kenkeiras/PyIC ]

Se puede ver como quedan las funciones en el README, pero los cambios básicamente son estos:

  • Lee el 'MOTD' automáticamente, se puede recuperar con irc.get_motd( ).
  • irc.get_users( ) devuelve la lista de usuarios, no hace falta leerlos a mano.
  • Lo mismo para irc.get_channels( ), que devuelve un array de tuplas( 'canal', 'número de usuarios', 'tema' ).
  • irc.get_topic( ) lo mismo, devuelve una string con el tema.
  • Y para no variar, lo mismo para irc.whois( ) y irc.whowas( ) , que devuelven un diccionario como este: { 'server_info': Información del servidor 'idle': 'seconds idle, signon time' 'real_name': Nombre real del usuario 'channels': Array de canales 'nick': Nick del usuario 'host': Dirección del host 'user': Nombre del usuario 'time': Tiempo conectado 'server': Server donde está conectado }

Enfín, por ejemplo:

!/usr/bin/env python

-- encoding: utf-8 --

PyIC example

from pyic import *

botName = "HelloBot" # NickName

server = "irc.freenode.net" # IRC server

channel = "#bot_testing" # IRC channel

greet = "Hello"

topic = "PyIC testing"

print "Connecting..."

irc = irc_client( botName, server ) # Connect

print "Message of the day:"

print irc.get_motd( )

print "Reading channel list"

print len( irc.get_channels( ) ), "channels"

print "Joining", channel

irc.join( channel ) # Joins the channel

irc.notice( channel, greet + " " + channel ) # talks to the channel

use notice in order to avoid automatic responses

Reads the user list

for usr in irc.get_users( channel ):

print '"' + usr + '" data'

print irc.whois( clean_usr( usr ) ) # Shows the user data

irc.notice( channel, greet + " " + usr ) # talks to the user

print "Setting channel topic"

irc.set_topic( channel, topic )

print "Topic:", irc.get_topic( channel )

print "Waiting for users..."

Greets who enters the channel

while ( True ):

msg = irc.getmsg( )

if ( msg.type.upper( ) == "JOIN" ): # Someone entered the channel

   if ( msg.by != botName ):



       print "'" + msg.by + "'", "has arrived"

       irc.notice( channel, greet + " " + msg.by )

       print irc.whois( msg.by )

Hasta la próxima

Acelerenado `route`, `netstat` y parecidos [tip]

Los comandos de red como route, netstat, e incluso programas como nmap tienen la constumbre de intentar convertir las IP's en nombres de red después de realizar su función principal. Por muy útil que sea a veces, en otros momentos es excesivamente pesado, por ejemplo si utilizamos:

===============================================================================

netstat

Para descubrir las conexiones activas, después de obtenerlas intentará convertir las IP en nombres de red, y en muchos normales no resultará en nada útil (seguramente acabe mostrando las IP o nombres genéricos).

Estos mismos comandos suelen aceptar el flag -n que evita esa resolución, el cambio salta a la vista:

Hasta otra

Evolvotron, un programa que hay que probar [offtopic]

Me voy a salir un poco de tema para recomendar un programa de "arte generativo", Evolvotron, lo que hace es mostrar al usuario unas imágenes de la que tiene que seleccionar una, así continuamente para encontrar con un algoritmo genético una imágen a gusto del usuario (requiere un poco de paciencia para cojerle el truco), la única parte mala es que según la web parece que no funciona en el SO de Microsoft (aunque es GPL y usa Qt y BOOST, no debería ser difícil portarlo).

Y con un poco de paciencia acabas con un wallpaper o con una galería como esta [ gigrafx_-_deviantart ]

Enfin, que si andais aburridos ya teneis que hacer :P

Comprobación de números primos con el FIPS186

Que no se diga, aquí está el código del algoritmo y una comprobación para ver el número de falsos positivos y negativos:

!/usr/bin/env python

-- encoding: utf-8 --

import random

""" FIPS186

Step 1. Set i = 1 and n > or = to 50.

Step 2. Set w = the integer to be tested, w = 1 + 2 a m, where m is odd and 2 a is m, where m is odd and 2 is the largest power of 2 dividing w - 1

Step 3. Generate a random integer b in the range 1 < b < w

Step 4. Set j = 0 and z = b**m mod w mod w

Step 5. If j = 0 and z = 1, or if z = w - 1, go to step 9

Step 6. If j > 0 and z = 1, go to step 8

Step 7. j = j + 1. If j < a, set z = z 2 mod w and go to step 5 mod w and go to step 5

Step 8. w is not prime. Stop.

Step 9. If i < n, set i = i + 1 and go to step 3. Otherwise, w is probably prime

"""

from math import sqrt

Comprobación real

def rchk(n):

for i in xrange(2,int(sqrt(n))+1):

   if not n % i:

       return False

return True

Especificada en el FIPS186

def chkprime(w, n = 50):

m = w-1

a = 0

while not m & 1:

   m >>= 1

   a += 1

i = 0

while True:

   b = random.randint(2, w-1)

   j = 0

   while True:

       z = (b**m) % w

       if ( j == 0 and z == 1) or \

         z == w-1:

           if (i

:

               i += 1

               break



           else:

               return True



       if j > 0 and z == 1:

           return False



       j += 1

       if j < a:

           z = ( z * z ) % w



       else:

           return False

fn = 0

fp = 0

pr = 0

inicio = 10

fin = 10000

import sys

for i in xrange(inicio,fin):

c = chkprime(i)

r = rchk(i)

if not i%100:

   sys.stdout.write("\r"+str(i)+" "+str(pr))

   sys.stdout.flush()

if c:

   pr += 1

if c != r:

   if c:

       fp += 1

       pr -= 1

   else:

       fn += 1

       pr += 1

print ""

print "Primos:", pr

print "Falsos negativos:", fn

print "Falsos positivos:", fp

Por ejemplo:

Primos: 1225 Falsos negativos: 608 Falsos positivos: 0 ===============================================================================

ps: se me pasó poner la licencia, como siempre está bajo WTFPL

Saludos

Introducción a la criptografia, con Python: DSA (V -2)

Después de 8 meses de demorar el momento de enfrentarse a DSA, continúa esta introducción a la criptografía ( aaaleluyaaaa... )

Pues seguimos con la introduccion a la criptografia... acababamos de ver el cifrado usando ElGamal y quedaba pendiente el algoritmo de firmado usando DSA para pasar a la sexta parte ( hashes de nuevo ), así que ahí vamos, documentación y código intercalado:

¿Que es DSA?
DSA (Digital Signature Algorithm, en español Algoritmo de Firma
digital) es un estándar del Gobierno Federal de los Estados Unidos
de América o FIPS para firmas digitales. Fue un Algoritmo propuesto
por el Instituto_Nacional_de_Normas_y_Tecnología de los Estados
Unidos para su uso en su Estándar de Firma Digital(DSS),
especificado en el FIPS 186. DSA se hizo público el 30_de_agosto de
1991, este algoritmo como su nombre lo indica, sirve para firmar y no
para cifrar información. Una desventaja de este algoritmo es que
requiere mucho más tiempo de cómputo que RSA o ElGamal, pero a
cambió las claves no tienen que ser tan grandes. [wikipedia]

Antes de empezar una cosa: el FIPS186 define un algoritmo para comprobar la primalidad, es bastante sencillo y hasta lo tenía implementado por ahí, peeeero... la lata dejó de funcionar y adiós. Enfin, que por ahora tiraremos con el mismo que el usado con RSA, que al fin y al cabo es solo ligeramente más lento pero da menos falsos negativos, con un poco de suerte mañana subo el código del test del FIPS186.

Para no variar, primero un trozo de código común con la implementación de RSA que se encarga de las mátematicas de forma eficiente, no es parte del protocolo pero es necesario para no desesperarse mientras firma algo.

!/usr/bin/env python

-- encoding: utf-8 --

"""

Copyright 2011 kenkeiras kenkeiras@gmail.com

Bajo la licencia WTFPL

        DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE



               Version 2, December 2004

Everyone is permitted to copy and distribute verbatim or modified

copies of this license document, and changing it is allowed as long

as the name is changed.

       DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  1. You just DO WHAT THE FUCK YOU WANT TO.

"""

import random

import sys

def genprimelist(t):

l = [2]

i = 3

while i < t :

   prime = True

   for c in l:



       if i % c == 0 :

           prime = False



           break

   if prime :

       l.append(i)



   i += 2

return l

Lista de primos precomputada con genprimelist(5000)

global primelist

primelist=[

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,

103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,

211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,

331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,

449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577,

587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,

709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839,

853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,

991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093,

1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,

1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327,

1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481,

1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597,

1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721,

1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867,

1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997,

1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113,

2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,

2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381,

2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,

2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671,

2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777,

2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909,

2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061,

3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217,

3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347,

3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499,

3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617,

3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761,

3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,

3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027,

4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,

4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327,

4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481,

4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637,

4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783,

4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933,

4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999]

Comprobación preliminar

def firstcheck(n):

global primelist

for p in primelist:

   if n%p==0:

       if n==p:



           return True

       else:

           return False

return True

Exponenciacion modular

def modex(base, exponente, modulo):

r = 1

while exponente > 0:

   if exponente &amp; 1:



       r = (r * base) % modulo



   exponente >>= 1

   base = (base * base) % modulo

return r

Comprobacion con un test de primalidad de Fermat

http://en.wikipedia.org/wiki/Fermat_primality_test

def fermattest(n,k=100):

for i in range (0,k):

   a=random.randint(1,n-1)

   if modex(a,n-1,n) != 1:



       return False

return True

def toBin(n):

l = []

while (n > 0):

l.append(n % 2)

n /= 2

return l

Comprobacion con el algoritmo de Miller-Rabin

http://snippets.dzone.com/posts/show/4200

def test(a, n):

b = toBin(n - 1)

d = 1

for i in xrange(len(b) - 1, -1, -1):

x = d

d = (d * d) % n

if d == 1 and x != 1 and x != n - 1:

 return True # Complex

if b[i] == 1:

 d = (d * a) % n

if d != 1:

return True # Complex

return False # Prime

Comprueba si es primo

def checkprime(n,k=100):

if (not firstcheck(n)):

   return False

if (not fermattest(n,k)):

   return False

for iteration in range(0,k):

   i=random.randint(1,n-1)



   if test(i,n):

       return False

return True

Multiplicacion modular inversa

[ http://en.wikipedia.org/wiki/Modular_multiplicative_inverse ]

def extended_gcd(a, b):

x, last_x = 0, 1

y, last_y = 1, 0

while b:

   quotient = a // b

   a, b = b, a % b



   x, last_x = last_x - quotient*x, x



   y, last_y = last_y - quotient*y, y

return (last_x, last_y, a)

Multiplicacion modular inversa

[ http://en.wikipedia.org/wiki/Modular_multiplicative_inverse ]

def inverse_mod(a, m):

x, q, gcd = extended_gcd(a, m)

if int(gcd) == 1:

   # x is the inverse, but we want to be sure a positive number is

returned.

   return (x + m) % m

else:

   # if gcd != 1 then a and m are not coprime and the inverse does not

exist.

   return None

Generar un numero primo de "bitn" bits y con una precision de "prec"

def genprime(bitn,k=100):

prime = random.randint(2(bitn-1),2bitn) #Esto se puede sustituir por una lectura a /dev/random, por ejemplo

prime |= 1 # Hacemos que sea impar

while not checkprime(prime,k):

   prime += 2

return prime

Nota: el archivo bien formateado y completo al final, que al meterlo en blogger hace una carnicería con los saltos de línea

Generación de claves

Según todos los sitios que hablan de este algoritmo, los dos primeros pasos son:

 1. p = a prime modulus, where 2L-1 < p < 2L for 512 = < L = <1024 and L a  
 multiple of 64  
 2. q = a prime divisor of p - 1, where 2159 < q < 2160

Trola! Si intentas hacer esto, intentando conseguir un par puedes ir a dar la vuelta al mundo mientras esperas, prueba de ello es este antiguo post [ "Eso pasa_por_no_leer" ]

Vamos, que lo primero que hay que hacer es obtener un q primo de 160 bits y después obtener un p a partir de p = q * 2 * n, en bonito:

def genP(q,bitn):

i = (bitn-1)-len(bin(q)[2:])

n = random.randint(1,1<<i)

qn = q * n

curr = (qn * (2*(bitn-len(bin(qn)[2:]))))

while len(bin(curr)[2:]) < bitn:

   curr <<= 1

return curr + 1

def genkeys(bitn):

p = q = None

while True:

   q = genprime(160)

   p = genP(q,bitn)

   if (checkprime(p)):

       break

Parece simple, verdad?, pues por culpa de esto esta parte tardó tanto tiempo XD

Después de esto todo es razonable:
3. g = h(p-1)/q mod p, where h is any integer with 1 < h < p - 1 such
that h(p-1)/q mod p > 1 (g has order q mod p)

g = h = None

pq = ((p-1)/q) # Precalculado, puede ser necesario

# usarlo varias veces

while True:

   h = random.randint(2,p-2)

   g = modex(h,pq,p)

   if g > 1:

       break

4. x = a randomly or pseudorandomly generated integer with 0 < x < q

x = random.randint(2,q-1)

5. y = gx mod p

y = modex(g,x,p)

En la documentación hablan de un sexto paso, generar un k aleatorio entre 0 y q, que no se incluirá en la clave privada ni en la pública, y que hay que regenerar cada vez que se firme algo ( en resumen, que es parte del proceso de firma pero a alguien se le cruzaron las neuronas )

La generación de claves ya está solo queda devolver los valores, la clave pública es y , la privada es x y otros datos genéricos ( que pueden ser compartidos por ciertos usuarios ) son: g, p y q
public = y

private = x

generic = (g,p,q)

return public, private, generic

Generación de firmas

Como con RSA, el documento se hasheará para firmarlo, así que utilizaremos esta función para obtener el hash como un número ( hace falta importar hashlib ) def SHA(msg):

return int(hashlib.sha1(msg).hexdigest(),16)

Vamos entonces con la generación de la firma: def sign(msg,private,generic):

r = s = None

g = generic[0]

p = generic[1]

q = generic[2]

while True:

k = a randomly or pseudorandomly generated integer with 0 < k < q

   k = random.randint(1,q-1) # Necesaria la mayor aleatoriedad

r = (gk mod p) mod q

   r = modex(g,k,p) % q

s = (k-1(SHA(M) + xr)) mod q

Nota: ese k-1 se refiere al inverso de k en q, (k * k-1) % q = 1
s = (inverse_mod(k,q)(SHA(msg) + (privater))) % q

Y se comprueba que r y s sean distintos de 0
if ( r != 0 ) and ( s != 0 ):

       break

La firma la componen r y s
return (r,s)

Comprobación de firmas

Toca entonces comprobar si nos han dado del palo, así comienza la comprobación de firmas (boilerplate-code): def checksign(msg,sign,pub,generic):

r = sign[0]

s = sign[1]

g = generic[0]

p = generic[1]

q = generic[2]

if ( r == 0 ) or ( s == 0 ):

   return False

Entonces, para las comprobaciones hacemos:
w = (s')-1 mod q

w = inverse_mod(s,q)

u1 = ((SHA(M')w) mod q

u1 = (SHA(msg)*w) % q

u2 = ((r')w) mod q

u2 = (r*w) % q

v = (((g)ul (y)u2) mod p) mod q

v = ((modex(g,u1,p)*modex(pub,u2,p)) % p ) % q

Y la firma será correcta si v == r
return v == r

El código completo [ dsa.py ], si se ejecuta directamente hará algunas comprobaciones

Saludos

[Referencias] FIPS_186 http://cryptodox.com/DSS http://es.wikipedia.org/wiki/Digital_Signature_Algorithm http://en.wikipedia.org/wiki/Digital_Signature_Algorithm

Obtener el número de bits de un número en Python [tip]

Perdón a los que les estoy rallando con esto de los tips, son cosas que cuando no se te ocurren no sabes de donde sacarlas, pero ya escritas son simples y obvias, sin más dilación:

def bitN(i):

return len(bin(i)[2:])

Me explico, se pasa a binario bin(i), se separa el número del indicador de formato [2:] (0b) y se muestra su longitud len( )

Saludos

Humo y espejos con el terminal y `cat`

Cross-posteado en el_blog_de_HackXCrack

Si alguna vez se te ocurrió lanzar un cat a un archivo que no fuera de texto, como una imágen o un ejecutable hay ciertas posibilidades de que notaras que había pasado algo raro cuando el comando volvió, el terminal "pensó" que habías escrito algunos caracteres... es más, si pulsaste [enter] para pasar a una línea limpia pensando que solo es basura que dejó el archivo, el terminal había intentado ejecutar el comando!

Me atreveré a decir que lo que pasó fue que en algún momento el cat mostró el par de caracteres \x1b Z ( \x1b es ESC ), mostrando algo como "62;9;c", hay más combinaciones que producen estos eventos pero esta, por ser la más corta, es la que tiene más probabilidades de darse por casualidad.

Todo esto viene porque el terminal emula un procolo antiguo, que acepta ciertas combinaciones de datos como caracteres de control (algo similar era en lo que se basaba el phreaking analógico :P ), aprovechando esto y esperando que el usuario también pulse instintivamente [enter] para pasar a una línea en blanco intentaremos que el usuario que lea un archivo ejecute un comando :), aunque la verdad sea dicha, estamos muy limitados.

Nota: aquí hablo del comando cat, pero pasa lo mismo con cualquiera que muestre algo directamente por pantalla, head, tail, un echo preparado o el programa que muestra un archivo que escribiste cuando aprendías.

Nota2: realmente todo esto tiene un motivo, pero si hay que profundizar en el protocolo el día de hoy se nos queda corto, si quieres hecharle un vistazo a sus entrañas revisa los links del final.

Pero empezemos por algo más sencillo, supongamos que queremos que el terminal deje de responder cuando lea un archivo, desde el terminal escribe esto: echo -e "\x1bP" > danger

Se generará un archivo "danger", si lo intentamos leer con cat el terminal se detendrá ( aunque la interfaz gráfica siga funcionanado sin problemas ).

Realmente lo que ha pasado es que ese código ( llamado "Device control" ) le indica al terminal que se ponga en modo "Graphics String Format" y intentará leer los datos que vienen detrás como pertenecientes a ese formato, hasta que encuentre otro código, ESC \ ("\x1b\"), que hará que salga de ese modo, así que si no lo incluimos, no será capaz de interpretar lo que muestre el cat después ni lo que el usuario teclee.

Bien, volvamos a lo nuestro, estas son las combinaciones interesantes que encontré hasta ahora:

===============================================================================

ESC: \x1b ESC c:borra la terminal ESC [ t: amplia hasta esas filas la terminal ESC Z ó ESC [c ó ESC [0c : el usuario teclea "62;9;c" en gnome-terminal "1;2c" en xterm ESC [5n : el usuario teclea "n" en xterm y gnome-terminal ESC [6n : el usuario teclea "1R" ó ";1R" si es a partir de la sexta línea ESC [?9h : convierte los clicks en el terminal en cadenas de caracteres que teclea el usuario ESC [13t : el usuario teclea "261;79t" ESC [14t : el usuario teclea "136;640t" ESC [18t : el usuario teclea ";;80t" ESC [19t : el usuario teclea ";52;180t" ESC [20t : el usuario teclea "LTerminal" ESC [21t : el usuario teclea "lTerminal" ESC [x : el usuario teclea "x" ESC P : corta el flujo datos hasta ESC \

===============================================================================

Si nos olvidamos de los números, que no nos sirven para nada, nos quedamos con esto:

===============================================================================

ESC [5n : el usuario teclea "n" en xterm y gnome-terminal ESC [x : el usuario teclea "x" ESC [20t : el usuario teclea "LTerminal" ESC [21t : el usuario teclea "lTerminal"

===============================================================================

Es decir, que si queremos que el usuario "teclee" nx, le pasaremos un archivo generado con esto: echo -e "\x1b[5n\x1b[0x" > danger

Como truco de magia está pasable, pero con solo las letras "n", "x" y las palabras "lTerminal" y "LTerminal" no podemos lograr gran cosa, como mucho ejecutar "nn", un lector de noticias.

Pero aquí no acaba todo, aún nos queda un truco bajo la manga, hay un código que nos permite leer los clicks en el terminal, y a que no adivinais como los muestra ? Sí, interpreta que los escribió el usuario :D

El código es:

===============================================================================

ESC [?9h

===============================================================================

Lo podemos activar con echo -e "\x1b[?9h"

Con esto solo podremos conseguir que ejecute comandos de dos letras ( después del código de cada posición el terminal añade un espacio. En fin, hechandole imaginación podemos intentar que ejecute el servidor X echo -e "\x1b[30t\x1bc\x1b[27;45fPulsa aqui[\x1b[7mX\x1b[0m]\x1b[?9h"

  • \x1b[30t : Para obtener suficientes filas y poder conseguir el código X;
  • \x1bc : Se deja la terminal en blanco
  • \x1b[27;45f : Saltamos a la fila 27, columna 45
  • Pulsa aqui[:Se muestra al usuario
  • \x1b[7m : Invierte el esquema de colores
  • X : Algo donde pulsar :P
  • \x1b[0m : Restaura el esquema de colores
  • ] : Se muestra por pantalla
  • \x1b[?9h : Para que convierta los clicks en las posiciones en códigos
    *

Y eso es todo, a portarse bien ;)

[Recursos] http://www.vt100.net/ http://www.windred.dk/avr/info/ascii-tabel_vt-codes.htm http://ascii-table.com/ansi-escape-sequences-vt-100.php

Adivina el lenguaje [solución]

Se ve que andamos con poca imaginación hoy, así que mientras tanto aquí va un pequeño reto, a ver si alguien consigue adivinar en que lenguaje esotérico está escrito este código: http://pastebin.com/Lb4qJtjY

Pista: lo que hace el código es mostrar por pantalla CodigoParaLlevar (sin el salto de línea de rigor :P )

Actualización: ya pasó un tiempo, así que esta_es_la_solución

Suerte

Cifrando con autómatas celulares

Hoy traigo un pequeño experimento, este es un cifrado que se basa en el mismo concepto que otro código anterior [ Un_autómata_celular_para_generar_números pseudo-aleatorios ], pero en vez de generar números aleatorios, sirve como cifrado de flujo [ http://pastebin.com/uX1WpGjF ] .

La idea es simple, se toma un campo de la variante "3-4 life" ya que genera patrones mas caóticos, se le introduce una figura que se sabe que se expande rápidamente [ http://videobin.org/+2be/2ly.html ], se avanza 200 generaciones, se hace XOR de las céldas y una clave ( cada celda con un bit de la clave ), y se vuelve a avanzar 75 generaciones.

Después los bits de cada estado hacen XOR con los bits correspondientes del archivo, se pasa al estado siguiente cuando se acaben los bits del anterior y se finaliza el programa cuando se haya cifrado todo el archivo.

Nota: Dudo que sea seguro por que, por ejemplo, hay más bits a 0 que a 1, cuando no debería ser así.

Sobre el script, si no se le pasan parámetros ya pide el la clave y los archivos, sino los parámetros son:

===============================================================================

./cell.py ["-"]

===============================================================================

El "-" (que en realidad puede ser cualquier cosa) lo único que hace es activar el mostrar los estados por los que pasa el autómata.

Hasta otra.