4

The full explanation of what I want to do and why would take a while to explain. Basically, I want to use a private SSL connection in a publicly distributed application, and not handout my private ssl keys, because that negates the purpose! I.e. I want secure remote database operations which no one can see into - inclusive of the client.

My core question is : How could I make the Python ssl module use data held in memory containing the ssl pem file contents instead of hard file system paths to them?

The constructor for class SSLSocket calls load_verify_locations(ca_certs) and load_cert_chain(certfile, keyfile) which I can't trace into because they are .pyd files. In those black boxes, I presume those files are read into memory. How might I short circuit the process and pass the data directly? (perhaps swapping out the .pyd?...)

Other thoughts I had were: I could use io.StringIO to create a virtual file, and then pass the file descriptor around. I've used that concept with classes that will take a descriptor rather than a path. Unfortunately, these classes aren't designed that way.

Or, maybe use a virtual file system / ram drive? That could be trouble though because I need this to be cross platform. Plus, that would probably negate what I'm trying to do if someone could access those paths from any external program...

I suppose I could keep them as real files, but "hide" them somewhere in the file system.

I can't be the first person to have this issue.

UPDATE

I found the source for the "black boxes"...

https://github.com/python/cpython/blob/master/Modules/_ssl.c

They work as expected. They just read the file contents from the paths, but you have to dig down into the C layer to get to this.

I can write in C, but I've never tried to recompile an underlying Python source. It looks like maybe I should follow the directions here https://devguide.python.org/ to pull the Python repo, and make changes to. I guess I can then submit my update to the Python community to see if they want to make a new standardized feature like I'm describing... Lots of work ahead it seems...

BuvinJ
  • 10,221
  • 5
  • 83
  • 96
  • With some background in the topic, I can tell you that all of this will not make the private key secure. Not even close. To protect a private key from access you will need a hardware encryptions device with secured storage. – Klaus D. May 13 '18 at 01:59
  • Thanks. Note taken. Unfortunately, that is way beyond the scope of what I'm looking to sell, and I'm not sure how that blocks the client from having access to the key? Requiring a physical device introduces radical differences to a business model, so that's a non starter. I want a downloadable, prepackaged program that can interact with a remote database in ways that "no one" can see into. This approach has potential security gaps, but it seems to at least be a step in the right direction compared to just handing out the same private key to every user with a bow on it. – BuvinJ May 13 '18 at 14:12

1 Answers1

3

It took some effort, but I did, in fact, solve this in the manner I suggested. I revised the underlying code in the _ssl.c Python module / extension and rebuilt Python as a whole. After figuring out the process for building Python from source, I had to learn the details for how to pass variables between Python and C, and I needed to dig into guts of OpenSSL (over which the Python module is a wrapper).

Fortunately, OpenSSL already has functions for this exact purpose, so it was just a matter of swapping out the how Python is trying to pass file paths into the C, and instead bypassing the file reading process and jumping straight to the implementation of using the ca/cert/key data directly instead.

For the moment, I only did this for Windows. Since I'm ultimately creating a cross platform program, I'll have to repeat the build process for the other platforms I'll support - so that's a hassle. Consider how badly you want this, if you are going to pursue it yourself...

Note that when I rebuilt Python, I didn't use that as my actual Python installation. I just kept it off to the side.

One thing that was really nice about this process was that after that rebuild, all I needed to do was drop the single new _ssl.pyd into my working directory. With that file in place, I could pass my direct cert data. If I removed it, I could pass the normal file paths instead. It will use either the normal Python source, or implicitly use the override if the .pyd file is simply put in the program's directory.

BuvinJ
  • 10,221
  • 5
  • 83
  • 96
  • Really nice work, is this available somewhere? – Daniel Sass Jun 26 '23 at 10:15
  • Thanks! Unfortunately, I haven't used that code, or thought much about this stuff, it in a few years. I may, however, be able to dig it up. I was thinking about getting another C library to to Python crossover running anyway. I'll let you know you in a day or so. – BuvinJ Jun 26 '23 at 12:52
  • Sorry, but I seem to have discarded the code! I found the pyd file I had produced, but not the source. I think I had modified the release in Python 2.7 to begin with, which is likely not what you want at this stage anyway. I'm pretty confident that it would not be too difficult to replicate what I did with a new version of Python, based on the description I've provided. – BuvinJ Jun 27 '23 at 12:44
  • Follow the instructions found at https://devguide.python.org/ to build a custom Python version. Modify the OpenSSL code in _ssl.c. Build Python, then copy the _ssl.pyd to your project's directory. It might take a day or so of work, depending on your experience with Python and C. My POC was the hardest part of the equation, rather than the task itself. – BuvinJ Jun 27 '23 at 12:48
  • If you want it, I could send you that .pyd for Py 2.7 on Windows... – BuvinJ Jun 27 '23 at 13:03
  • Not necessary, we are already on 3.11. Thank you – Daniel Sass Jun 28 '23 at 10:31