如何通过python ssl socket进行重新协商

时间:2015-07-30 00:20:17

标签: python ssl handshake

我需要通过python模拟一个重新协商行为(我将其理解为新的握手)。这可能吗?

我尝试了下面的代码,第一个do_handshake工作,但第二个没有做任何事情。

import socket, ssl, pprint, re, time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

ssl_sock = ssl.wrap_socket(s,ca_certs="cacert.pem",do_handshake_on_connect=False)

ssl_sock.connect(('172.18.7.162', 443))
time.sleep(3)
ssl_sock.do_handshake()
print repr(ssl_sock.getpeername())
print ssl_sock.cipher()
print pprint.pformat(ssl_sock.getpeercert())

send_content="aaaa"
ssl_sock.write(send_content)
time.sleep(2)
print "do_handshake_again"
ssl_sock.do_handshake()
print "do_handshake_again done"

ssl_sock.write(send_content)

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

回答我自己的问题: 最后,我使用python openssl lib实现了这种行为。

from OpenSSL import SSL
import sys, os, select, socket
........
# Initialize context
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_options(SSL.OP_NO_SSLv2)

#ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb) # Demand a certificate
ctx.use_privatekey_file (os.path.join(dir, 'server.pkey'))
ctx.use_certificate_file(os.path.join(dir, 'server.cert'))
ctx.load_verify_locations(os.path.join(dir, 'CA.cert'))

# Set up server
server = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
server.bind(('', int(sys.argv[1])))
server.listen(3)
server.setblocking(0)

........

    for cli in w:
        try:
            ret = cli.send(writers[cli])
            cli.renegotiate()      
            cli.do_handshake()
            ret = cli.send(writers[cli])
......

重要的是最后4行: 1,用socket发送东西 2-3,触发重新协商并做握手 4,再次发送信息

因为它是非阻塞套接字,我可以看到这个代码发出两个数据包:第一个数据包只发送应用程序数据(内容类型23),第二个数据包将有两个有效负载:一个是ssl握手(类型22)另一个是应用数据(类型23)。

顺便说一句,这是试图模拟重新协商数据包在同一个数据包中有应用数据。如果对于纯tls重新协商,我们可以使用openssl发送“R”来触发纯tls重新协商行为。