Generar claves ssh desde python sin meter contraseña

Para un proyecto hace un par de semanas estuvimos jugando con la generación de claves ssh-rsa desde python, que para la conexión automática segura entre servidores resulta de lo más cómodo. Buscando algo de información llegamos rápido a varios hilos en Stackoverflow hablando sobre el tema, aunque finalmente nos tuvimos que meter un poco en código. :-)

        from M2Crypto import RSA
        from base64 import b64encode
        import os

        key = RSA.gen_key(1024, 65537)
        raw_key = key.pub()[1]
        b64key = b64encode(raw_key)

        username = os.getlogin()
        hostname = os.uname()[1]
        key.save_key("/.ssh/%s" % login, callback=lambda v: "")
        keystring = 'ssh-rsa %s %s@%s' % (b64key, username, hostname)

        #devolvemos la clave pública
        return keystring
<p>Opté por trabajar con la conocida biblioteca <a href="http://chandlerproject.org/bin/view/Projects/MeTooCrypto">M2Crypto</a>, con la que ya había jugado para temas de SSL, ignorando el certificado para <em>xmlrpc</em>.</p>

En el ejemplo anterior generamos una clave RSA de 1024 bits, con un exponente RSA de 65537. Tomamos los datos de la parte pública con pub() y lo desciframos en base64. usamos los datos de la maquina del usuario y su login para añadirlo a la clave pública final.

Con save_key guardamos la clave privada ssh en formato PEM en el directorio que queramos con el nombre que queramos (normalmente en el $HOME/.ssh). Devolvemos la clave pública por si queremos hacer algo con ella (enviarla a una máquina con subprocess o lo que se nos ocurra :-) )

def passphrase_callback(v, prompt1='Enter passphrase:',
                           prompt2='Verify passphrase:'):
    from getpass import getpass
    while 1:
        try:
            p1=getpass(prompt1)
            if v:
                p2=getpass(prompt2)
                if p1==p2:
                    break
            else:
                break
        except KeyboardInterrupt:
            return None
    return p1

En este caso, podemos crear una función que se ocupe de introducir la contraseña para generar la clave final privada. En el ejemplo de M2Crypto en util.passphrase_callback se le preguntará al usuario qué contraseña quiere y se comprobará una segunda vez (código de arriba).

Usando el método ejemplo en util.passphrase_callback lo más sencillo fue finalmente implementarlo de una manera correcta, añadiendo como callback (como vemos en el código de más arriba) la función lambda.

...
key.save_key("/.ssh/%s" % login, callback=lambda v: "")
...

Al querer contraseña vacía basta con pasarle como callback una función lambda que recoja el parámetro de la función, devuelva vacío y listo. :-)

Javier Aguirre

Read more posts by this author.

comments powered by Disqus