Can't import pgp key using gnupg - python

I'm trying to import a public key provided to me in python but for some reason the code always says "no fingerprint found" for this key. I've been able to use the same code to import another public gpg key. The only difference is that the one i was able to import looks normal when opening in a text file
-----BEGIN PGP MESSAGE-----
hQIMA4KP8a3P3lh+ARAArIKl7NQQ2nwLrbScEXB4YwHK8PaBU/zvcO4flo9XHfhj
...
-----END PGP MESSAGE-----
while the other one looks like a bunch of jumbled characters. snippit of jumbled file
Here is the python code i am using to do my import
import boto3
import os
import gnupg
from pprint import pprint
gpg = gnupg.GPG()
#commented out part where i pull file from s3 to /tmp/Public_key.txt
public_keys = gpg.list_keys()
private_keys = gpg.list_keys(True)
print ('public keys:')
pprint(public_keys)
print ('private keys:')
pprint(private_keys)
# import
key_data = open('/tmp/Public_Key.txt').read()
import_result = gpg.import_keys(key_data)
for k in import_result.results:
print("printing import results public key")
print(k)
Things i have tried are: reading the file as binary instead which also didn't work
with open('/tmp/Public_Key.txt', mode='rb') as file: # b is important -> binary
key_data = file.read()
Another thing to note, the key is able to be imported easily when i use CLI from my terminal using
gpg --import Public_Key.txt
So is it because i need to convert it to a string first that is messing it up?
The output of the import attempt in python is
{'fingerprint': None, 'status': 'No valid data found'}

Related

Gnupg not out-puting encrypted file

Im trying to import a public key, read a csv file, encrypt that file and store that encrypted file in a folder/ directory. The program runs but nothing seems to be generated, created or outputed after I run the script. Any suggestions.
import gnupg
gpg = gnupg.GPG(gnupghome='./gnupghome')
key_data = open('./datafiles/public_key.txt').read()
import_result = gpg.import_keys(key_data)
encrypted_ascii_data = gpg.encrypt('./datafiles/myFile.csv', key_data, output="./datafiles/myFile.csv.gpg")
The second parameter is a list of recipients. You're passing it the key_data. If you check the the result of your call to gpg.encrypt(...), you'll see that you have:
>>> encrypted_ascii_data.status
'invalid recipient'
You need to either specify an explicit recipient (by fingerprint, email address, etc), or extract a recipient from your imported key, like this:
>>> encrypted_ascii_data = gpg.encrypt('./datafiles/myFile.csv',
... import_result.fingerprints[0],
... output="./datafiles/myFile.csv.gpg")
But this will still probably fail with:
>>> encrypted_ascii_data.stderr
'[GNUPG:] KEY_CONSIDERED ... 0\ngpg: 426D9382DFD6A7A9: There is no assurance this key belongs to the named user\n[GNUPG:] INV_RECP 10 ...\n[GNUPG:] FAILURE encrypt 53\ngpg: [stdin]: encryption failed: Unusable public key\n'
It looks like you need to set up a trust for that key. Before attempting to use the key:
gpg.trust_keys(import_result.fingerprints, 'TRUST_ULTIMATE')
Once you've done this:
>>> encrypted_ascii_data = gpg.encrypt('./datafiles/myFile.csv',
... import_result.fingerprints[0],
... output="./datafiles/myFile.csv.gpg")
>>> encrypted_ascii_data.status
'encryption ok'

import PGP public key block as string : working in shell but not in python-gnupg

apologies in advance if I am duplicating a post(please point me at it etc. ?): I see a lot of documentation/Q&A on exporting armored keys but not much around how to import blocks in string format. I am unable to replicate in python what I can do on the windows commandline direct with the following:
gpg2 --import <textfilecontaining public key block in python code below>
which returns:
gpg: key 2FD34F7F: public key "name (comment) <em#il>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
I used the python-gnupg library in python, as below:
import gnupg, tempfile, shutil
pubkey = '''-----BEGIN PGP PUBLIC KEY BLOCK-----
xsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj
t1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O
CfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa
qKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO
VaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57
vilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp
IDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV
CAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/
oO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5
crfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4
bjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn
iE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp
o4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI=
=XQoy
-----END PGP PUBLIC KEY BLOCK-----'''
"""that block, minus the enveloping triple-quotes,
is all that's inside the file I am importing at the commandline
"""
tempfolder = tempfile.mkdtemp()#creates a temp directory
try:
gpg = gnupg.GPG(homedir=tempfolder)
keyfile = tempfolder+"\\test.txt"#defining temp pubkey file
f = open(keyfile, 'w')
f.write(pubkey)#saves file with string content
f.close()
f = file(keyfile, 'r')
f.close()
importres = gpg.import_keys(keyfile)
print importres
print importres.results
currfingerprint = gpg.list_keys()
print currfingerprint
finally:
shutil.rmtree(tempfolder)#removes temp directory
which returns:
<gnupg._parsers.ImportResult object at 0x00000000038A8400>
[{'status': 'No valid data found', 'fingerprint': None}]
[]
... It seems my Python implementation isn't recognising this file/string representation somehow. Wonder if someone could point me in the right direction with Python please? I have tried dearmor-ing the string content(binascii.a2b_base64) but to no avail. I'd prefer not to use bog-standard subprocess here. Perhaps some stoopid indentation fessup?
env=Windows10, Python 2.7
Your code sample is passing the name of a file containing the key to import_keys:
keyfile = tempfolder+"\\test.txt"#defining temp pubkey file
...
importres = gpg.import_keys(keyfile)
However, the import_keys function does not accept a file name and read from that file. Instead, it expects to receive the actual key file content. For example, here is a simplified version of the program that just passes pubkey directly to import_keys without using a temporary file:
import gnupg
pubkey = '''-----BEGIN PGP PUBLIC KEY BLOCK-----
xsBNBFVjnlIBCACibzXOLCiZiL2oyzYUaTOCkYnSUhymg3pdbfKtd4mpBa58xKBj
t1pTHVpw3Sk03wmzhM/Ndlt1AV2YhLv++83WKr+gAHFYFiCV/tnY8bx3HqvVoy8O
CfxWhw4QZK7+oYzVmJj8ZJm3ZjOC4pzuegNWlNLCUdZDx9OKlHVXLCX1iUbjdYWa
qKV6tdV8hZolkbyjedQgrpvoWyeSHHpwHF7yk4gNJWMMI5rpcssL7i6mMXb/sDzO
VaAtU5wiVducsOa01InRFf7QSTxoAm6Xy0PGv/k48M6xCALa9nY+BzlOv47jUT57
vilf4Szy9dKD0v9S0mQ+IHB+gNukWrnwtXx5ABEBAAHNFm5hbWUgKGNvbW1lbnQp
IDxlbUBpbD7CwHUEEwECACkFAlVjnlIJEINgJNgv009/AhsDAhkBBgsJCAcDAgYV
CAIJCgsEFgIDAQAAxqMIAFBHuBA8P1v8DtHonIK8Lx2qU23t8Mh68HBIkSjk2H7/
oO2cDWCw50jZ9D91PXOOyMPvBWV2IE3tARzCvnNGtzEFRtpIEtZ0cuctxeIF1id5
crfzdMDsmZyRHAOoZ9VtuD6mzj0ybQWMACb7eIHjZDCee3Slh3TVrLy06YRdq2I4
bjMOPePtK5xnIpHGpAXkB3IONxyITpSLKsA4hCeP7gVvm7r7TuQg1ygiUBlWbBYn
iE5ROzqZjG1s7dQNZK/riiU2umGqGuwAb2IPvNiyuGR3cIgRE4llXH/rLuUlspAp
o4nlxaz65VucmNbN1aMbDXLJVSqR1DuE00vEsL1AItI==XQoy
-----END PGP PUBLIC KEY BLOCK-----'''
gpg = gnupg.GPG()
importres = gpg.import_keys(pubkey)
print importres
print importres.results
currfingerprint = gpg.list_keys()
print currfingerprint
The output of this version is:
<gnupg._parsers.ImportResult object at 0x10d1cd910>
[{'status': 'Entirely new key\n', 'fingerprint': u'A3F68FF91ABFE2486D830E99836024D82FD34F7F'}]
[{'dummy': u'', 'keyid': u'836024D82FD34F7F', 'expires': u'', 'rev': {}, 'sigs': {u'name (comment) <em#il>': []}, 'subkeys': [], 'length': u'2048', 'ownertrust': u'-', 'algo': u'1', 'fingerprint': u'A3F68FF91ABFE2486D830E99836024D82FD34F7F', 'date': u'1432591954', 'trust': u'-', 'type': u'pub', 'uids': [u'name (comment) <em#il>']}]
If you need something that works by importing from a file, then you'll need to write some additional code to read in the contents of the file into a variable first, and then pass that to import_keys. (Alternatively, you could fall back to a subprocess solution to call straight to gpg --import like you mentioned.)

How to get private key from paramiko in string?

How to get private key in string from below...
key = paramiko.RSAKey.generate(1024)
ssh_key = 'ssh-rsa' + key.get_base64()
Updated: I wanted to get Private Key from the ssh_key variable, any idea how to get it?
Like,
-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAswAD2ZlxCGm3Cy9y9diAnCh+Ji7SUnsbC1SEquqRatM7hCKS\nt3D1NFWLZrNrKUw3bgENLL1Umv5wQ9Sb42rA3TTKgjikeMiJg4tQtqSKDvjC1eq6\nMbQzqzTpjDD/WGk9cFTauurVHPk0MMwCPNUTCzQrYiM6yNKmySQ3tRFvZLSu1RLJ\ngK93qPIDPjqxUwEWtb8clu1Dt+q7hKpB+cQBXLGfUTa/1LLQFSPhZ5jwjuAaLXnE\nz0QYpwqn1OgG4t7yXYSpFWu37ItoHGKu6tmhxiPZ9rywFGqgzFMqMJCD2Qn2Fl6P\nCLWxSZvak1/rbMyx1627ZfZhKfplyzjvSevyJQIDAQABAoIBABggzmQMfOIHbfcC\nBFsDPgLOqoJ3GT6o/XI/iEqJp+RgaMtc5a34efT9+vZzBOTiMy6O0bnQI5Fo7rUV\n+ZVkFG886Hc5L2Jglbi3lL+p2jo+afTv2P1OLxDK5xhQmnrOZMu5hGphsSxgoxpY\nxYxxpEmEVLy7xva+/mBqk1/C4+MNBhpBgFuMtT03FcYJGwD9G5CwAP1uCyT8xfF3\nby8IXVSE3li65Q0lUk1SUu0I8DOSJdZcB2c8J9J8/Hop6sJx8UBwyIJ9zV1sWZ00\nzWFKdgnF1UDQecaub0pt/4cuZ9seUJxBPAvFi2tLQIENJs+higFW535T40TYARvR\nzfNIUFkCgYEA46RRftlmNcvSam+wW2SvNZ34Ygrod1bAiCy2ld5zAuAKQdiKyoKJ\nKwrrHOIr5XkmLRddn4QPFC80O+jD4Ek1PDdvjxkVJUKvFXwqzbzkTehEABPxtwFj\nTB+bVOH0Fkh6qf15UAsQ6C+NTJMC1b88S5mT7zQw6y/cr6i2Os0+bacCgYEAyUx4\na7eKnGVuVUDdpiRVVzeMuOHwunDQ3EirQ5hYOnKfDVPGRwpXkDbjns8m/o0cAg1r\njguGL5H0ApRhrODQnCwqwA5aolWn9Ou5sDPREL6ji5Dn/iQevx5HOOcKzsYbnwS7\nC0Ng/47SkvodOBURE5G1KJn/X1osYE3lAh59E1MCgYA0/rb+OexCj92/a5r529my\nOMFvSazOw4J08TvcbfoGbFPW+mttM7BtNdCAW+LuPCL4El14Wk0MXOTjIZAgMcrT\n5u/wt10l3H1YGhz44oWf4XebMQlvmkIcoasOur+RRHRSCLFqQflApHlXn03kpu2J\niApZgKP2zKCqwDMUQ13KNwKBgGSP00jctF5VPb1RXml1lTyw/5gNJ5m8alrh4s0t\n+kWYpWSfCVrMC9p70VKw4iYgkHFmCuk3UJ3LKD9xqSoYVZ7vYZv4j8axS+rLKESi\nXjsjQcijZ4JKwSFxGtuOcJPD3GCgmGCUFI0W6JOMZ7Rwscs462uRI0abYbfqshFQ\n8eMJAoGBALV38hiL7jy5kMi83Y17XEZ9qsTQbofkUaqieI2BdE5qWaVICkTKrt50\nM7FVe56CLwtpIZxGg3R1nO8zBT0aDOT7qKWXRw9C2jNMbJoI+rDM93m4lku/NirO\nLevEvuunmIk+ukyuoieKmqBOGpqJBk1uBZg0Owhqxq4ezq6ZI6Fy\n-----END RSA PRIVATE KEY-----\n
Any idea? Thanks in advance...
Use the write_private_key() method of the key object:
import StringIO
out = StringIO.StringIO()
key.write_private_key(out)
print out.getvalue()
You also need to reset the StringIO (using Python 3)
from io import StringIO
out = StringIO()
key.write_private_key(out)
out.seek(0)
key_str = out.read()

How do use paramiko.RSAKey.from_private_key()?

Any idea how I can use the paramiko.RSAKey.from_private_key() function?
I know there is a from_private_key_file(), but I'm interested in using a function to parse a private key (like below) and use that private key for SSHClient.
Private key (sample):
-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKCAIEAmfgmlY95SHXhCeBNdkhSrsG4JVbqyew845yoZRX3wcS2/doz\niVQxgx0aiOwLi+/Rnkb3PLUIwoxb/LoD/W0YMS6/NSUMt+LdH+zsjeNF2iq4rDzU\nwDSqi27q/8u/egrK7H+9HNKEVXb/87utAAm3VTM9KqKaK3VuVFrNrnsDSuECAwEA\nAQKCAIBZn3y2KiGq8BLiMNJmO4sFdnW+Jm3cw8pdo17SGItzGxJ5iX3ePkfjzhkY\nAm5mMl6OBzj6+VX0CMeywIR6C/q8HwDYSmZcuU5v76/DoW5bI6xkPrroqEz6aRE5\nyN+2hf65RD3eoPATsdrP/kxiKjZg9uG9LhgIXyVwYFs1RcqewQJBAMCVJlEYXRio\neynUtyES9HNmUGUqHKmri1FZfO56/mFdG5ZXsKE48qURCAGVxI+goGQ4vtJIXB2J\nyTEr+5qYtE0CQQDMq9/iigk+XDOa9xGCbwxbLGdPawaEivezMVdPqVzH971L6kZ8\nhEnev1DqujgGCyR+QYPW1ZCXH05FY9CqWwrlAkATzYJyJlI0XebER2ZJVVyjnSq5\nLFpkLAqYY95P23/a3SsgC4ZTHbr9tEGhgBgFONwlUhx1HRGzy95PWxl1LSylAkBk\nwP93v8gJIM5urM27zfrhLxy0ZdVRji+d0N5QYuk/r19KbcvBJEZRFxE4W++UWgve\n81V5fqytGEYptpdUJXlZAkEArxZDiT1HXXGciIgzZbh53McogPCGHiKOOPSjpM41\npneDFVvwgezCWoDauxNDzu7Nl55qPJsmvfKZ+SKvCajrhQw==\n-----END RSA PRIVATE KEY-----\n
Code I wanted to run:
import paramiko
ssh = paramiko.SSHClient()
# how do I pass in the private_key, when my private_key (shown above) is in string?
mykey = paramiko.RSAKey.from_private_key(private_key)
ssh.connect('192.168.1.2', username = 'vinod', pkey = mykey)
Many thanks.
Lev's method worked for me:
>>> import paramiko
>>> f = open('/path/to/key.pem','r')
>>> s = f.read()
>>> import StringIO
>>> keyfile = StringIO.StringIO(s)
>>> mykey = paramiko.RSAKey.from_private_key(keyfile)
>>> ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
>>> ssh.connect('myserver.compute-1.amazonaws.com', username='ubuntu', pkey=mykey)
>>> stdin, stdout, stderr = ssh.exec_command('uptime')
>>> stdout.readlines()
[' 19:21:10 up 24 days, 42 min, 1 user, load average: 0.14, 0.06, 0.05\n']
This should do it:
import io
import paramiko
private_key_file = io.StringIO()
private_key_file.write('-----BEGIN RSA PRIVATE KEY-----\nlskjdflk\n...\n-----END RSA PRIVATE KEY-----\n')
private_key_file.seek(0)
private_key = paramiko.RSAKey.from_private_key(private_key_file)
from_private_key() apparently takes a file object:
from_private_key(cls, file_obj, password=None)
Create a key object by reading a private key from a file (or file-like) object. If the private key is encrypted and password is not None, the given password will be used to decrypt the key (otherwise PasswordRequiredException is thrown).
Parameters:
file_obj (file) - the file to read from
password (str) - an optional password to use to decrypt the key, if it's encrypted
Returns: PKey
a new key object based on the given private key
Raises:
IOError - if there was an error reading the key
PasswordRequiredException - if the private key file is encrypted, and password is None
SSHException - if the key file is invalid
So to feed it a key as a string you can use StringIO, something like:
private_key = StringIO.StringIO(key_string)
mykey = paramiko.RSAKey.from_private_key(private_key)
I have not tested this, though.
Here is where 'duck typing' comes in handy - it does not have to BE a duck (=file), it just has to BEHAVE like one.
A little experimentation shows that, any object that has a valid readlines() method is fine.
I faked it with:
def myfakefile(keystring):
myfakefile.readlines=lambda: keystring.split("\n")
return myfakefile
mykey = paramiko.RSAKey.from_private_key(myfakefile(keystring))
This is incredibly hacky, but it works.
What this does, is, when you call myfakefile(keystring), it creates myfakefile.readlines, which returns the (split) contents of keystrings.
Then, it returns the function.
The same function is passed to from_private_key. from_private_key, thinking it is a file, calls myfakefile.readlines(). This calls the newly created (lambda) function, which returns the sort of thing you would expect from file.readlines() - or, close enough, anyway.
Note that, saving the results will not work as expected:
k1=myfakefile(keystring1)
k2=myfakefile(keystring2)
# This will return keystring2, not keystring1!
paramkiko.RSAKey.from_private_keyfile(k1.readlines())
There are more robust methods of getting this to work as it should, but not worth the effort - just use StringIO if your needs are more complicated.
Very old question, but in case it helps some unfortunate soul: my sol'n to this problem was to generate a new key with default options, using
ssh-keygen -t rsa
My previous key was generated using
ssh-keygen -t rsa -b 4096 -a 100
which paramiko complained about as it did for OP.

How to generate SSH key pairs with Python

I'm attempting to write a script to generate SSH Identity key pairs for me.
from M2Crypto import RSA
key = RSA.gen_key(1024, 65337)
key.save_key("/tmp/my.key", cipher=None)
The file /tmp/my.key looks great now.
By running ssh-keygen -y -f /tmp/my.key > /tmp/my.key.pub I can extract the public key.
My question is how can I extract the public key from python? Using key.save_pub_key("/tmp/my.key.pub") saves something like:
-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADASDASDASDASDBarYRsmMazM1hd7a+u3QeMP
...
FZQ7Ic+BmmeWHvvVP4Yjyu1t6vAut7mKkaDeKbT3yiGVUgAEUaWMXqECAwEAAQ==
-----END PUBLIC KEY-----
When I'm looking for something like:
ssh-rsa AAAABCASDDBM$%3WEAv/3%$F ..... OSDFKJSL43$%^DFg==
Use cryptography! pycrypto is not in active development anymore and if possible you should be using cryptography. Since June it's possible to generate SSH public keys as well:
from cryptography.hazmat.primitives import serialization as crypto_serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend as crypto_default_backend
key = rsa.generate_private_key(
    backend=crypto_default_backend(),
    public_exponent=65537,
    key_size=2048
)
private_key = key.private_bytes(
    crypto_serialization.Encoding.PEM,
    crypto_serialization.PrivateFormat.PKCS8,
    crypto_serialization.NoEncryption()
)
public_key = key.public_key().public_bytes(
    crypto_serialization.Encoding.OpenSSH,
    crypto_serialization.PublicFormat.OpenSSH
)
Note: You need at least version 1.4.0.
Note: If your SSH client does not understand this private key format, replace PKCS8 with TraditionalOpenSSL.
Just in case there are any future travellers looking to do this. The RSA module support writing out the public key in OpenSSH format now (possibly didn't at the time of earlier posts). So I think you can do what you need with:
from os import chmod
from Crypto.PublicKey import RSA
key = RSA.generate(2048)
with open("/tmp/private.key", 'wb') as content_file:
chmod("/tmp/private.key", 0600)
content_file.write(key.exportKey('PEM'))
pubkey = key.publickey()
with open("/tmp/public.key", 'wb') as content_file:
content_file.write(pubkey.exportKey('OpenSSH'))
The files are opened with a 'wb' as the keys must be written in binary mode.
Obviously don't store you're private key in /tmp...
Edit 05/09/2012:
I just realized that pycrypto already has this:
import os
from Crypto.PublicKey import RSA
key = RSA.generate(2048, os.urandom)
print key.exportKey('OpenSSH')
This code works for me:
import os
from Crypto.PublicKey import RSA
key = RSA.generate(2048, os.urandom)
# Create public key.
ssh_rsa = '00000007' + base64.b16encode('ssh-rsa')
# Exponent.
exponent = '%x' % (key.e, )
if len(exponent) % 2:
exponent = '0' + exponent
ssh_rsa += '%08x' % (len(exponent) / 2, )
ssh_rsa += exponent
modulus = '%x' % (key.n, )
if len(modulus) % 2:
modulus = '0' + modulus
if modulus[0] in '89abcdef':
modulus = '00' + modulus
ssh_rsa += '%08x' % (len(modulus) / 2, )
ssh_rsa += modulus
public_key = 'ssh-rsa %s' % (
base64.b64encode(base64.b16decode(ssh_rsa.upper())), )
The key used by ssh is just base64 encoded, i don't know M2Crypto very much, but after a quick overview it seems you could do what you want this way:
import os
from base64 import b64encode
from M2Crypto import RSA
key = RSA.gen_key(1024, 65537)
raw_key = key.pub()[1]
b64key = b64encode(raw_key)
username = os.getlogin()
hostname = os.uname()[1]
keystring = 'ssh-rsa %s %s#%s' % (b64key, username, hostname)
with open(os.getenv('HOME')+'/.ssh/id_rsa.pub') as keyfile:
keyfile.write(keystring)
I didn't test the generated key with SSH, so please let me know if it works (it should i think)
The base64 decoded version of ssh-keygen output to the contents of key.pub() the format of the keyfile is
b64encode('\x00\x00\x00\x07ssh-rsa%s%s' % (key.pub()[0], key.pub()[1]))
If you want, you could just also use ssh-keygen itself.
You can extend this to also create your file, and just use open to read the content later, but i focused on creating a .pub key from an already existing key here.
from subprocess import Popen, PIPE
import os
home = f'{os.path.expanduser("~")}'
cert_pos = f'{home}/.ssh/my_key'
your_key_pw = ''
cmd = ['ssh-keygen', '-y', '-f', cert_pos]
if your_key_pw:
cmd.append('-P')
cmd.append(your_key_pw)
p = Popen(cmd, stdout=PIPE)
p.wait()
res, err = p.communicate()
cert_content = res.decode('utf-8')
Here is an example using the Twisted Conch library which leverages PyCrypto under the covers. You can find the API documentation at http://twistedmatrix.com/documents/current/api/twisted.conch.ssh.keys.html:
from twisted.conch.ssh import keys
# one-time use key
k="""-----BEGIN RSA PRIVATE KEY-----
PRIVATE KEY STUFF
-----END RSA PRIVATE KEY-----"""
# create pycrypto RSA object
rsa = keys.RSA.importKey(k)
# create `twisted.conch.ssh.keys.Key` instance which has some nice helpers
key = keys.Key(rsa)
# pull the public part of the key and export an openssh version
ssh_public = key.public().toString("openssh")
print ssh_public
You can use pycryptodome as described in documentation:
from Crypto.PublicKey import RSA
key = RSA.generate(2048)
private_key = key.export_key()
file_out = open("private.pem", "wb")
file_out.write(private_key)
public_key = key.publickey().export_key()
file_out = open("receiver.pem", "wb")
file_out.write(public_key)
Just guessing... but have you tried something like this?:
print "ssh-rsa " + "".join([ l.strip() for l in open('/tmp/my.key.pub') if not l.startswith('-----')])
Can you get the AAAA...Dfg== string out of it while it's an object? If so, you could simply open a file yourself and save that instead of using the built in save_pub_key function.
I don't know of such a library that comes standard with Python.
If you want to look to third-party libraries, you might find the paramiko library useful (also available from PyPI). It implements the SSH protocol, and has functionality for handling existing keys, but not generating them.
Generation of keys might be a useful addition to that library (you could work with the developers to incorporate it into the Paramiko library), and an easier start than doing it from scratch.

Categories

Resources