使用 .pem 证书和 Python 的 SSL 连接 [英] SSL Connection Using .pem Certificate With Python

查看:49
本文介绍了使用 .pem 证书和 Python 的 SSL 连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用身份验证通过 HTTPS 连接建立成功的通信.我在 Ubuntu 12.04 上使用 Python 2.7 和 Django 1.4.

I'm trying to establish successful communication over an HTTPS connection using authentication. I'm using Python 2.7 w/ Django 1.4 on Ubuntu 12.04.

我所关注的 API 文档对身份验证有特定要求.包括您将在下面找到的 Authentication 标头和发送证书信息.

The API documentation I'm following has specific requirements for authentication. Including the Authentication header you'll find below and sending certificate information.

这是代码:

import httplib
import base64

HOST = 'some.host.com'
API_URL = '/some/api/path'

username = '1234'
password = '5678'

auth_value = base64.b64encode('WS{0}._.1:{1}'.format(username, password))
path = os.path.join(os.path.dirname(__file__), 'keys/')
pem_file = '{0}WS{1}._.1.pem'.format(path, username)

xml_string = '<some><xml></xml><stuff></stuff></some>'

headers = { 'User-Agent'     : 'Rico',
            'Content-type'   : 'text/xml',
            'Authorization'  : 'Basic {0}'.format(auth_value),
          }



conn = httplib.HTTPSConnection(HOST, cert_file = pem_file)
conn.putrequest("POST", API_URL, xml_string, headers)
response = conn.getresponse()

我收到以下错误:

Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/csrf.py" in wrapped_view
  77.         return view_func(*args, **kwargs)
File "/home/tokeniz/tokeniz/gateway_interface/views.py" in processPayment
  37.         processCreditCard = ProcessCreditCard(token, postHandling)
File "/home/tokeniz/tokeniz/gateway_interface/credit_card_handling.py" in __init__
  75.             self.processGateway()
File "/home/tokeniz/tokeniz/gateway_interface/credit_card_handling.py" in processGateway
  95.         gateway = Gateway(self)
File "/home/tokeniz/tokeniz/gateway_interface/first_data.py" in __init__
  37.         self.postInfo()
File "/home/tokeniz/tokeniz/gateway_interface/first_data.py" in postInfo
  245.         response = conn.getresponse()
File "/usr/lib/python2.7/httplib.py" in getresponse
  1018.             raise ResponseNotReady()

Exception Type: ResponseNotReady at /processPayment/
Exception Value: 

为什么我会收到此错误?

Why am I getting this error?

更新1:我一直在使用他们给我的 .pem 文件(链接点网关),但读到证书文件应该包含证书和 RSA 私钥.那是对的吗?我尝试发送包含两者的 .pem 文件并收到以下错误:

UPDATE 1: I've been using the .pem file they gave me (Link Point Gateway) but have read that the certificate file should contain both the certificate and the RSA private key. Is that correct? I tried to send a .pem file containing both and received the following error:

    Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/csrf.py" in wrapped_view
  77.         return view_func(*args, **kwargs)
File "/home/tokeniz/tokeniz/gateway_interface/views.py" in processPayment
  37.         processCreditCard = ProcessCreditCard(token, postHandling)
File "/home/tokeniz/tokeniz/gateway_interface/credit_card_handling.py" in __init__
  75.             self.processGateway()
File "/home/tokeniz/tokeniz/gateway_interface/credit_card_handling.py" in processGateway
  95.         gateway = Gateway(self)
File "/home/tokeniz/tokeniz/gateway_interface/first_data.py" in __init__
  37.         self.postInfo()
File "/home/tokeniz/tokeniz/gateway_interface/first_data.py" in postInfo
  251.         conn.request('POST', self.API_URL, self.xml_string, headers)
File "/usr/lib/python2.7/httplib.py" in request
  958.         self._send_request(method, url, body, headers)
File "/usr/lib/python2.7/httplib.py" in _send_request
  992.         self.endheaders(body)
File "/usr/lib/python2.7/httplib.py" in endheaders
  954.         self._send_output(message_body)
File "/usr/lib/python2.7/httplib.py" in _send_output
  814.         self.send(msg)
File "/usr/lib/python2.7/httplib.py" in send
  776.                 self.connect()
File "/usr/lib/python2.7/httplib.py" in connect
  1161.             self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
File "/usr/lib/python2.7/ssl.py" in wrap_socket
  381.                      ciphers=ciphers)
File "/usr/lib/python2.7/ssl.py" in __init__
  141.                                         ciphers)

Exception Type: SSLError at /processPayment/
Exception Value: [Errno 336265225] _ssl.c:351: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib

我不知道这是前进还是后退.

I can't tell if this is a step forward or backward.

更新2:我尝试在创建连接对象时同时传递证书文件和密钥文件.

UPDATE 2: I've tried to pass both a certificate file and a key file when creating the connection object.

conn = httplib.HTTPSConnection(HOST, cert_file = pem_file, key_file = key_file)

我收到以下错误:

Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/csrf.py" in wrapped_view
  77.         return view_func(*args, **kwargs)
File "/home/tokeniz/tokeniz/gateway_interface/views.py" in processPayment
  37.         processCreditCard = ProcessCreditCard(token, postHandling)
File "/home/tokeniz/tokeniz/gateway_interface/credit_card_handling.py" in __init__
  75.             self.processGateway()
File "/home/tokeniz/tokeniz/gateway_interface/credit_card_handling.py" in processGateway
  95.         gateway = Gateway(self)
File "/home/tokeniz/tokeniz/gateway_interface/first_data.py" in __init__
  37.         self.postInfo()
File "/home/tokeniz/tokeniz/gateway_interface/first_data.py" in postInfo
  252.         conn.request('POST', self.API_URL, self.xml_string, headers)
File "/usr/lib/python2.7/httplib.py" in request
  958.         self._send_request(method, url, body, headers)
File "/usr/lib/python2.7/httplib.py" in _send_request
  992.         self.endheaders(body)
File "/usr/lib/python2.7/httplib.py" in endheaders
  954.         self._send_output(message_body)
File "/usr/lib/python2.7/httplib.py" in _send_output
  814.         self.send(msg)
File "/usr/lib/python2.7/httplib.py" in send
  776.                 self.connect()
File "/usr/lib/python2.7/httplib.py" in connect
  1161.             self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
File "/usr/lib/python2.7/ssl.py" in wrap_socket
  381.                      ciphers=ciphers)
File "/usr/lib/python2.7/ssl.py" in __init__
  141.                                         ciphers)

Exception Type: SSLError at /processPayment/
Exception Value: [Errno 336265225] _ssl.c:351: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib

如果我尝试合并证书文件和密钥文件并将其作为证书参数发送,我会收到相同的错误.

If I try and combine the certificate file and key file and send it as the certificate argument I receive the same error.

推荐答案

Python 中的某些更高级别"库似乎没有配备处理这种身份验证连接的能力.经过多天的尝试,我终于能够想出一个深入到套接字级别的解决方案.

It would seem that some of the "higher level" libraries in Python are not equipped to handle this kind of authentication connection. After many days of attempts I was finally able to come up with a solution going down to the socket level.

host = 'some.host.com'
service = '/some/api/path'
port = 443

# Build the authorization info
username = '1234'
password = '5678'
path = '/path/to/key/files/'
pem_file = '{0}WS{1}._.1.pem'.format(path, username)
key_file = '{0}WS{1}._.1.key'.format(path, username)
auth = base64.b64encode('WS{0}._.1:{1}'.format(username, password))

## Create the header
http_header = "POST {0} HTTP/1.0\nHost: {1}\nContent-Type: text/xml\nAuthorization: Basic {2}\nContent-Length: {3}\n\n"
req = http_header.format(service, host, auth, len(xml_string)) + xml_string

## Create the socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn = ssl.wrap_socket(sock, keyfile = key_file, certfile = pem_file)
conn.connect((host, port))
conn.send(req)

response = ''
while True:
    resp = conn.recv()
    response += resp

    if (resp == ''):
        break

我希望有人觉得这很有用.这个特定的实现是用 Python 与链接点网关接口(First Data(链接点)不支持).谈论整个项目的噩梦.哈哈

I hope someone finds this useful. This particular implementation was to interface with Link Point Gateway with Python (not supported by First Data (Link Point)). Talk about a nightmare this whole project has been. haha

无论如何,对于在使用 Link Point 时遇到问题的任何人,请注意他们提供的 .key 文件不足以在 Python 中创建连接.

Anyway, for anyone having trouble using Link Point please be advised that the .key file they provide you is not sufficient for creating a connection in Python.

openssl rsa -in orig_file.key -out new_file.key

然后使用 new_file.key 代替.

这篇关于使用 .pem 证书和 Python 的 SSL 连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆