0

My Question

I'm trying to use an encrypted client private key when using python requests. As it doesn't support encrypted keys, I have to decrypt it first and then send it to requests. The problem is that requests only accepts file paths for specifying client keys/certificates. How can I make it accept a string?

Example of what I want to do:

#X509
CLIENT_CERT_PATH = "path/to/cert" #perhaps I should convert this into a string too?

#PKey
CLIENT_PKEY_STRING = decrypt("path/to/encrypted_key")

response = requests.get(url = url, cert = (CLIENT_CERT_PATH, CLIENT_PKEY_STRING)) #how?

Attempts

Tried Python requests CA certificates as a string but I got the following behaviour: AttributeError: module 'urllib3.contrib' has no attribute 'pyopenssl'.

Also tried Example of including a certficate in a post request with python and http.client and even adapted it to look like:

class openSSLContext(requests.packages.urllib3.util.ssl_.SSLContext):
    def __init__(self, method):
        pk = crypto.load_privatekey(crypto.FILETYPE_PEM, open(CL_PKEY_PATH, "rb").read())
        cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(CL_CERT_PATH, "rb").read())
        

requests.packages.urllib3.util.ssl_.SSLContext = openSSLContext

but I don't know where to go from here.

Versions

Python 3.9.2
pyOpenSSL == 20.0.1
requests == 2.25.1
urllib3 == 1.26.4
136
  • 1,083
  • 1
  • 7
  • 14

1 Answers1

0

EDIT: The bellow code doesn't work

If you want to modify the second example you gave the bellow should do it

class openSSLContext(requests.packages.urllib3.util.ssl_.SSLContext):
    def __init__(self, method):
        pk = crypto.load_privatekey(crypto.FILETYPE_PEM, open("./key.pem", "rb").read())
        cert = crypto.load_certificate(
            crypto.FILETYPE_PEM, open("./cert.pem", "rb").read()
        )
        self.certfile = cert
        self.keyfile = pk


requests.packages.urllib3.util.ssl_.SSLContext = openSSLContext
Teh
  • 139
  • 1
  • 6
  • How would I modify the second awnser (the one I tried to adapt)? – 136 Mar 24 '21 at 04:06
  • sadly didn't work :( edited the post with the errors – 136 Mar 24 '21 at 04:24
  • 1
    You forgot to pass the method argument in `__init__` and `super.__init__` – Teh Mar 24 '21 at 04:27
  • already fixed that. I get a different error now – 136 Mar 24 '21 at 04:29
  • This is a patch and terible code by try passing `OpenSSL.SSL.TLSv1_2_METHOD` instead of `method` `in super().__init__` – Teh Mar 24 '21 at 04:56
  • `AttributeError: 'PatchedContext' object has no attribute 'set_ciphers'` now – 136 Mar 24 '21 at 04:58
  • shouldn't the new context extend `requests.packages.urllib3.util.ssl_.SSLContext` somehow? trying this shows: `File "C:\Faculdade\SSIN\proj\src\client\services.py", line 21, in __init__ super().__init__(method) TypeError: object.__init__() takes exactly one argument (the instance to initialize)` – 136 Mar 24 '21 at 05:01
  • You are completely right fixed the coded and tested it should work now – Teh Mar 24 '21 at 05:17
  • your solution doesn't crash now, but the requests still aren't being authorized. I think the statements `self.certfile = cert` and `self.keyfile = pk` aren't doing anything – 136 Mar 24 '21 at 05:25
  • Well sorry but at this point I have no idea, I hope someone else is able to help – Teh Mar 24 '21 at 06:41