controlling puttygen with Popen

2019-07-07 04:59发布

I'm writing a python script to generate SSH keys for users. After generating them using ssh-keygen, I'd like to use puttygen to create a .ppk file. Unfortunately, puttygen doesn't allow the passphrase to be provided on the commandline - therefore I'm trying to pipe them into its stdin using popen. It always complains of a 'wrong passphrase', but entering the commands at the commandline and entering the passphrase there works fine - the problem is something in my popen technique. puttygen prompts three times for a passphrase - once to read the openssh-generated key, and twice for the key for the new file. Puttygen reports an error after the first prompt, so the problem is with my attempt to send the passphrase to the subprocess.

The platform is Ubuntu 11.10, python 2.7, latest openssh and putty-tools packages. Here's a chopped-out script to illustrate the problem I'm having:

#!/usr/bin/python
import sys, os, subprocess

KEYGEN = "/usr/bin/ssh-keygen -t rsa -b 4096 -f id_rsa -N passphrase"
PUTTYGEN = "/usr/bin/puttygen id_rsa -P -O private -o test.ppk"
phrase = "passphrase"

try:
    os.unlink('id_rsa')
except:
    pass

try:
    os.unlink('id_rsa.pub')
except:
    pass

try:
    os.unlink('test.ppk')
except:
    pass

## generate the public and private keys
subprocess.call(KEYGEN.split(' '))

## convert key to PuTTY format
p = subprocess.Popen(PUTTYGEN.split(' '), 
                     stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)

## Two techniques I've tried - also tried variations on CR/LF.  No luck.
if False:
    o, e = p.communicate(phrase + '\n' + phrase + '\n' + phrase + '\n')
    #o, e = p.communicate(phrase + '\r' + phrase + '\r' + phrase + '\r')
    #o, e = p.communicate(phrase + '\r\n' + phrase + '\r\n' + phrase + '\r\n')

    print o
    print e

else:
    p.stdin.write(phrase + '\n')
    p.stdin.write(phrase + '\n')
    p.stdin.write(phrase + '\n')

    print p.stdout.read()
    print p.stderr.read()
    p.stdin.close()

    p.wait()

标签: python popen
2条回答
Explosion°爆炸
2楼-- · 2019-07-07 05:19

It seems like puttygen reads all three passphrases as first one. The simplest solution is to insert

time.sleep(0.1) 

between

p.stdin.write(phrase + '\n')
查看更多
孤傲高冷的网名
3楼-- · 2019-07-07 05:24

puttygen (0.69 in my case) has new options: '--old-passphrase file' - specify file containing old key passphrase, '--new-passphrase file' - specify file containing new key passphrase. It answers the passphrase via 'stdin' issue.

查看更多
登录 后发表回答