XMLRPC con ssl (https). Generador de contraseñas y chequeador de fortaleza de las mismas (python)

GECO's picture

El proyecto sigue avanzando paso a paso. Hoy he implementado un frontend para el demonio de GECO (gecod) que implementa una interfaz XMLRPC con ssl.

Dado que vamos a mandar información sensible hacia el servidor es necesario que la conexión se haga a través de un canal seguro, por lo tanto he buscado por ahí la forma de tener un servidor xmlrpc en python sobre ssl y lo he encontrado.

A partir de ese código he creado el módulo python secure_xmlrpc. Y básandome en este, crear un servidor XMLRPC sobre ssl es tan fácil como declarar una clase y pasarle una instancia de esta al constructor de la clase EasyServer.

...
import secure_xmlrpc as sxmlrpc
...
class frontend:
...
def auth(self, user, password):
...

def start_server():
sxmlrpc.EasyServer(HOST, PORT, frontend())
...

Por otra parte, en el lado del cliente, he empezado creando un módulo (utils) el cual ahora mismo tiene un generador de contraseñas "aleatorias" y una función que comprueba la seguridad de una contraseña de forma simple.

Para generar una contraseña aleatoria he usado los módulos random y string. Está parametrizado el conjunto de caracteres a utilizar y el tamaño de la contraseña generada. Con random.choice y una lista por comprensión genero la contraseña a partir del conjunto de caracteres seleccionado.

import random
import string

LOWER, UPPER, DIGITS, PUNCT = (string.lowercase,
string.uppercase,
string.digits,
'.:;,!?{}[]=-_()+')

def generate(size=11, lower=True, upper=True, digits=True,
punctuation=False):

chars = ''
selection = [lower, upper, digits, punctuation]
strings =(LOWER, UPPER, DIGITS, PUNCT)

for opt, v in zip(selection, strings):
if opt:
chars += v

return ''.join([random.choice(chars) for _ in xrange(size)])

Para comprobar la seguridad de las contraseñas he implementado una función que comprueba características básicas de las contraseñas y devuelve un valor entre 0 y 1.

Los test que he implementado son:

  • contraseña en una lista de palabras
  • la contraseña es una secuencia ordenada
  • según el tamaño (=14)
  • la contraseña contiene algún caracter (minusculas, mayusculas, digitos, puntuación)
def strength(password):
'''
return 0..1
'''

strength = -5

# bad passwords tests (-20 or -15)
bad_passwords = ('', 'qwerty', 'asdf', 'zxcv', '123', '1234')
if password in bad_passwords:
return -20
ord_pass = [ord(i) for i in password]
inverted_pass = ord_pass[:]
inverted_pass.reverse()
if is_sorted(ord_pass) or is_sorted(inverted_pass):
return -15

# len tests (min -10, max 5)
if len(password) strength -= 10
elif len(password) strength -= 8
elif len(password) strength -= 5
elif len(password) >= 14:
strength += 5

# chars tests (max +20)
for chars_string in LOWER, UPPER, DIGITS, PUNCT:
for j in chars_string:
if j in password:
strength += 5
break

return ((strength + 20) / 40.0)

def is_sorted(alist):
'''
alist is a list of ints
'''

first = alist[0]
i = 1
while i if first != alist[i] - 1:
return False
first = alist[i]
i += 1
return True

Con esto y un bizcocho, podremos generar contraseñas y verificar su seguridad con suma facilidad.