Public key not recognized - python

I am trying to export a public key from openssl using python. I have the actual key information transferred to the client from the server but the PEM encoding is not transferred so the key on the client is useless. I basically send the public key using send all in python but unfortunately this does not send the PEM encoding. Does anyone know how to transfer the encoding?
I didn't know that the encoding would not transfer along with the key.
THe code where the string is read in
import socket
import M2Crypto as m2c
import os
max_transfer_block = 1024
server_addr = "10.1.1.2"
dest_port = 3333
listen_port = 8888
client_addr = "10.1.1.3"
mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysocket.connect((server_addr, dest_port))
#receive the public key from the server
keysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
keysocket.bind((client_addr, listen_port))
keysocket.listen(1)
conn, client_addr = keysocket.accept()
print 'connected by', client_addr
data = conn.recv(max_transfer_block)
#FILE = m2c.RSA.save_pub_key(data, "serverPubKey.pem")
FILE = open("sPub.pem", "w")
FILE.write(data)
keysocket.close()
#transfer encrypted file
key = m2c.RSA.load_pub_key('serverPubKey.pem')
FILE = open("test.txt", "r")
data = FILE.read()
encrypted = key.public_encrypt(data, m2c.RSA.pkcs1_padding)
mysocket.sendall(encrypted)
mysocket.close()
When I use the line key = m2c.RSA.load_pub_key('serverPubKey.pem') I get an error telling me that there is no starting point.
raise RSAError, m2.err_reason_error_string(m2.err_get_error()) M2Crypto.RSA.RSAError: no start line
I have figured out that this is because there is not in PEM format. Unfortunately, I don't know how to put it in that format.

The mistake was that the public/private key pair needs to be created from the same wrapper. What I mean by this is that not all key pairs are the same. My specific problem was that Openssl and the M2Crypto instances of key pairs were not in the same underlying format. Thus creating keys with Openssl and then trying to use M2Crypto to use the keys was wrong. The lesson from all of this is to not import keys from other wrappers. If you do, make sure that they are in the same underlying format like ASCII or Unicode before trying to use them.

Related

How to extract RSA public-key from x509 certificate in python

I have the following script. It connects to a TLS server and extracts X509 certificate public-key:
import socket, ssl
import OpenSSL
hostname='www.google.com'
port=443
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(s, server_hostname=hostname)
ssl_sock.connect((hostname, port))
ssl_sock.close()
print("ssl connection Done")
cert = ssl.get_server_certificate((hostname, port))
# OpenSSL
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
pk = x509.get_pubkey()
print(pk)
The problem is that the returned public-key. I need it in hexadecimal format. How to solve this issue?
This is the output I am getting:
<OpenSSL.crypto.PKey object at 0x0000019EBFDF73C8>
I'm not exactly sure what you're asking for. It would be helpful to paste in the output you received (it looks like you forgot to). This may not bee what you're looking for, but it's worth a try (untested, also you must import binascii):
print(binascii.hexlify(pk.to_cryptography_key().public_key().public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo))
You should modify the encoding and format to fit your needs.
EDIT: I think I understand what you're trying to do now. You may want to change the encoding to Encoding.PKCS1.
#pk = x509.get_pubkey() # from your code.
IntPk = pk.to_cryptography_key().public_numbers()
print(IntPk.n)# modulus
print(IntPk.e)# exponent
In python3, arbitrary-precision arithmetic is default.
so decryption is possible like below:
pow(signature, e, n))# (a**b)%c is by pow(a, b, c)

Can't pickle an RSA key to send over a socket

I have a list with a public key and a username that I want to send over a socket.
I found
how to send an array over a socket in python but using pickling won't work either.
My code:
private_key = generateRSA()
public_key = private_key.public_key()
host = ''
port = 8000
username = sys.argv[1]
mySocket = socket.socket()
mySocket.connect((host, port))
dataToSend = [public_key, username.encode()]
dataSend = pickle.dumps(dataToSend)
mySocket.send(dataSend)
The error in the console says
dataSend = pickle.dumps(dataToSend)
_pickle.PicklingError: Can't pickle <class '_cffi_backend.CDataGCP'>: attribute lookup CDataGCP on _cffi_backend failed
The key was generated with the cryptography library.
You are trying to send a RSAPublicKey instance, but this is a data structure managed by SSL, not Python. Because you interact with it through a CFFI proxy, you can't pickle one of these.
You'll need to pick a key serialization format to send it instead. You could convert to PEM, for example:
from cryptography.hazmat.primitives import serialization
pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
The above would export your key to a string value you could then convert to bytes and send over the socket directly. The other side would load the key from that string again.
Note that the above uses no encryption whatsoever. Anyone intercepting the traffic over that socket would be able to read your public key. That may or may not be a problem for your application.

socket error in python 2.7, sending public rsa key to client

I'm programming a client-server communication encrypted with RSA, using tcp sockets. I generate public and private keys, but when I want to exchange the public keys between client and server I get this error:
TypeError: must be convertible to a buffer, not PublicKey
This is server code:
import socket
import rsa
print "Generating keys"
(public, private) = rsa.newkeys(1024, poolsize=2)
print "Keys generated."
tcpSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
tcpSocket.bind(("0.0.0.0", 1025))
tcpSocket.listen(1)
print "Waiting for client..."
(client, (ip, port)) = tcpSocket.accept()
print "Connection received from: ", ip
client.send(public) #This is where I get the error
I've tried with this line too:
client.send(str(public))
With this I can send the public key, but then I can't use it to encrypt data (because now the public key is a string).
Thank you for your help !
You can use Pickle or cPickle:
import cPickle
to_send=cPickle.dumps(the_key)
sock.send(to_send)
And then unpickle it:
import cPickle
s=sock.recv()
key=cPickle.loads(s)

decrypt ssl encrypted data in python

I'm analyzing a packet capture with python using dpkt. The application layer is encrypted with ssl. I'd like to decrypt the ssl data (i.e., the tcp payload). I have the private key, so I should be able to use the key to decrypt the data. Here's my script:
#!/bin/python
import sys
import dpkt
def main():
if not len(sys.argv) == 2:
print "need a pcap file"
return 1
filename = sys.argv[1]
f = open(filename)
pcap = dpkt.pcap.Reader(f)
framenum = 1
for ts, buf in pcap:
if framenum == 123:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
tcp = ip.data
ssl = tcp.data
# decrypt ssl
framenum += 1
if __name__ == '__main__':
sys.exit( main() )
What can I put in place of that "decrypt ssl" comment to get the decrypted ssl bytes? I'm guessing there should be some library that can do this for me, but all my searches for ssl and python give information about writing socket programs that can receive ssl connections. I'm not interested in that. Rather, I need to decrypt data that is encrypted with ssl.
Thanks!
You're not likely going to find a ready-made library to do this. Decrypting from a packet dump is rather involved, and I believe the best featured tool right now is still Wireshark.
Note that you will also need to have the entire TLS session captured, from the handshake onward. Also, if the connection used an ephemeral mode which offers forward secrecy (anything with DHE or ECDHE), the data cannot be decrypted.

Can't send correct value over a socket using Python

I'm new to using Python and sockets in general (only started yesterday) so I've been having a lot of issues trying to set up a TCP client and server. The issue I'm having is that I want to send a key from the server to the client. I know that the server grabs the key correctly as it prints out the correct key, however it has a 0 appended to it in a new line and when the key is sent to the client the only thing that is displayed is " b'0' ".
I've made very little progress due to my lack of experience and after searching for hours I still haven't found a solution to my problem.
Here is the server code:
import os
from socket import * #import the socket library
HOST = '' #We are the host
PORT = 29876
ADDR = (HOST, PORT)
BUFFSIZE = 4096
message = 'Hello, World!'
serv = socket( AF_INET,SOCK_STREAM)
serv.bind(ADDR,)
serv.listen(5)
print ('listening...')
conn,addr = serv.accept()
print (conn,addr)
print ('...connected')
key = os.system("cat ~/.ssh/id_rsa.pub")
conn.send(str(key))
print (key)
conn.close()
Here is the client code
from socket import *
import os
HOST = 'xxx.xxx.xxx.xxx'
PORT = 29876
ADDR = (HOST,PORT)
BUFFSIZE = 4096
message = "Hello, World!"
cli = socket( AF_INET, SOCK_STREAM)
cli.connect(ADDR,)
data = cli.recv(BUFFSIZE)
print (data)
cli.close()
As you can tell from my code I'm using Python 3.3
Any help with this issue is greatly appreciated.
os.system() does not return the process's output, but the return value (ie. integer 0).
If you only want to read a file, do it manually:
with open(os.path.expanduser("~/.ssh/id_rsa.pub")) as f:
key = f.read()
conn.sendall(key)
If you need process output, read the documentation for the subprocess module.

Categories