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'
I have been trying for a few days to validate some message signed with a private key in python. Note that the message has been signed using Ruby.
When I sign the same message in python I can verify it no problem. Note that I have already validated that the hash are the same.
Python code:
string_to_encrypt = b"aaaaabbbbbaaaaabbbbbaaaaabbbbbCC"
sha1 = SHA.new()
sha1.update(string_to_encrypt)
# load private key
pkey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, open('./license.pem', 'rb').read())
sign_ssl = OpenSSL.crypto.sign(pkey, sha1.digest(), 'RSA-SHA1')
b64_ssl = base64.b64encode(sign_ssl)
Ruby:
string_to_encrypt = "aaaaabbbbbaaaaabbbbbaaaaabbbbbCC"
sha1 = Digest::SHA1.digest(string_to_encrypt)
#sign it
private_key_file = File.join(File.dirname(__FILE__), 'license.pem')
rsa = OpenSSL::PKey::RSA.new(File.read(private_key_file))
signed_key = rsa.private_encrypt(sha1)
#update the license string with it
x = Base64.strict_encode64(signed_key)
I would expect b64_ssl and x to contain the same value and they don't. Could someone explain to me what I missing there?
Neither of these code snippets is actually producing the correct signature.
In the Ruby OpenSSL library you want to be using the sign method, not the private_encrypt method, which is a low level operation that doesn’t do everything required to produce a valid signature.
In both libraries the sign operation performs the hashing for you, you don’t need to do this beforehand. In fact your Python code is actually hashing the data twice.
Try the following Python code:
import OpenSSL
import base64
string_to_encrypt = b"aaaaabbbbbaaaaabbbbbaaaaabbbbbCC"
# load private key
pkey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, open('./license.pem', 'rb').read())
sign_ssl = OpenSSL.crypto.sign(pkey, string_to_encrypt, 'SHA1')
b64_ssl = base64.b64encode(sign_ssl)
print(b64_ssl.decode())
which produces the same output as this Ruby code:
require 'openssl'
require 'base64'
string_to_encrypt = "aaaaabbbbbaaaaabbbbbaaaaabbbbbCC"
#sign it
private_key_file = File.join(File.dirname(__FILE__), 'license.pem')
rsa = OpenSSL::PKey::RSA.new(File.read(private_key_file))
signed_key = rsa.sign('sha1', string_to_encrypt)
#update the license string with it
x = Base64.strict_encode64(signed_key)
puts x
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()
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.
M2Crypto package is not showing the 'recipient_public_key.pem' file at linux terminal.
How do I get/connect with recipient public key.
Exactly, I need to check how can I open this file through linux commands.
import M2Crypto
def encrypt():
recip = M2Crypto.RSA.load_pub_key(open('recipient_public_key.pem','rb').read())
print recip;
plaintext = whatever i need to encrypt
msg = recip.public_encrypt(plaintext,RSA.pkcs1_padding)
print msg;
after calling the function its not giving any output and even any error
i also tried as 'Will' said
pk = open('public_key.pem','rb').read()
print pk;
rsa = M2Crypto.RSA.load_pub_key(pk)
what is the mistake I am not getting?
I have never used M2Crypto, but according to the API documentation, load_pub_key expects the file name as the argument, not the key itself. Try
recip = M2Crypto.RSA.load_pub_key('recipient_public_key.pem')