sta*_*arm 14 python openssl cryptography pyopenssl m2crypto
我很难运行带有EXPORT级密码的M2Crypto SSLServer.
LOW/MEDIUM/HIGH级密码的工作没有任何问题,但EXPORT不会.此外,当OpenSSL从命令行以服务器模式运行时,它接受EXPORT级密码而没有任何问题.
所以,要么我丢失了某些东西,要么M2Crypto模块中存在问题.任何帮助表示赞赏.
使用过的python代码(ssl-server.py)如下所示:
import M2Crypto
import socket
CERTFILE = "dummy_cert.pem"
KEYFILE = "dummy_key.pem"
PROTOCOL = "sslv3"
HOST = "0.0.0.0"
PORT = 4433
def main():
print "[i] Initializing context ..."
ctx = M2Crypto.SSL.Context(protocol=PROTOCOL, weak_crypto=True)
ctx.load_cert_chain(certchainfile=CERTFILE, keyfile=KEYFILE)
ctx.set_options(M2Crypto.m2.SSL_OP_ALL)
ctx.set_cipher_list("ALL")
print "[i] Initializing socket ..."
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
conn, addr = sock.accept()
print "[i] SSL handshake ..."
ssl_conn = M2Crypto.SSL.Connection(ctx=ctx, sock=conn)
ssl_conn.setup_ssl()
try:
ssl_conn_res = ssl_conn.accept_ssl()
except Exception, ex:
print "[x] SSL connection failed: '%s'" % str(ex)
else:
if ssl_conn_res == 1:
print "[i] SSL connection accepted"
else:
print "[x] SSL handshake failed: '%s'" % ssl_conn.ssl_get_error(ssl_conn_res)
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
症状是:
$ uname -a
Linux XYZ 2.6.38-15-generic #59-Ubuntu SMP Fri Apr 27 16:03:32 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=11.04
DISTRIB_CODENAME=natty
DISTRIB_DESCRIPTION="Ubuntu 11.04"
$ python -c "import M2Crypto;print M2Crypto.version_info"
(0, 20, 1)
$ openssl version
OpenSSL 0.9.8o 01 Jun 2010
1) NOT OK
SERVER (terminal 1): $ python ssl-server.py
CLIENT (terminal 2): $ openssl s_client -connect localhost:4433 -cipher EXPORT
CONNECTED(00000003)
28131:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:602:
2) OK
SERVER (terminal 1): $ openssl s_server -cert dummy_cert.pem -key dummy_key.pem -ssl3 -no_tls1 -no_ssl2 -cipher EXPORT
CLIENT (terminal 2): $ openssl s_client -connect localhost:4433 -cipher EXPORT
CONNECTED(00000003)
depth=0 C = BE, CN = www.example.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = BE, CN = www.example.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 C = BE, CN = www.example.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/C=BE/CN=www.example.com
i:/C=BE/CN=test-ca
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=/C=BE/CN=www.example.com
issuer=/C=BE/CN=test-ca
---
No client certificate CA names sent
---
SSL handshake has read 1141 bytes and written 242 bytes
---
New, TLSv1/SSLv3, Cipher is EXP-EDH-RSA-DES-CBC-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: zlib compression
Expansion: zlib compression
SSL-Session:
Protocol : SSLv3
Cipher : EXP-EDH-RSA-DES-CBC-SHA
Session-ID: B052D5D5A436F9A0B9D3FB24F2E32A8A06A0B6828230621C4CFAEB82A0A9AE0C
Session-ID-ctx:
Master-Key: 47F6E3720D06518B961FE389F13BCDE42C37F703099ABBB9B3DA35383C420F519D4F4773D35E470CF6FF7BB243B29069
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Compression: 1 (zlib compression)
Start Time: 1340644713
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
Run Code Online (Sandbox Code Playgroud)
a的内容dummy_cert.pem如下:
-----BEGIN CERTIFICATE-----
MIICkTCCAfqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJCRTEQ
MA4GA1UEAxMHdGVzdC1jYTAeFw0xMjA1MDYwODQyNDlaFw0yMjA1MDMwODQyNDla
MCcxCzAJBgNVBAYTAkJFMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wgZ8wDQYJ
KoZIhvcNAQEBBQADgY0AMIGJAoGBAL7OBv9wRwtNjN984XSy22/rw6tHM6Lq/Ccf
NoHKbqwC+PsxgmgJJiGBGewrzBR42toqHJi7EjHhuvrgqV9s2duPQBAANh7tzY1h
6VekrwhIIt4o1h0F2KB16VXA8s918d+8pRGt2T11GUh/QT3m9yY1VzqdIBeAfklC
ET6ncPK/AgMBAAGjgdQwgdEwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAw
KwYJYIZIAYb4QgENBB4WHFRpbnlDQSBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD
VR0OBBYEFNGQArEZPKprJTn7A64qEFfl0m4xME8GA1UdIwRIMEaAFFuITOUJlGrJ
9lKufs8cm1MpwXrroSOkITAfMQswCQYDVQQGEwJCRTEQMA4GA1UEAxMHdGVzdC1j
YYIJALimgW7YUgdrMAkGA1UdEgQCMAAwCQYDVR0RBAIwADANBgkqhkiG9w0BAQUF
AAOBgQDWh8A0eBxI9XHy68xdjFsk2oerJeV6qqlcmtPZgz3GlarRcWcKsRJOyLLL
dCOe7tY5isWQAoLt6XALzDWjbQkTJnxBaKHif1MIikuajaYKT7LA1MvFn50Qrm6n
f9hG7gvdTpm1rlPcs0qibp1vJVubkU51mT6JT4UnLfeVIjtL7Q==
-----END CERTIFICATE-----
Run Code Online (Sandbox Code Playgroud)
a的内容dummy_key.pem如下:
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQC+zgb/cEcLTYzffOF0sttv68OrRzOi6vwnHzaBym6sAvj7MYJo
CSYhgRnsK8wUeNraKhyYuxIx4br64KlfbNnbj0AQADYe7c2NYelXpK8ISCLeKNYd
BdigdelVwPLPdfHfvKURrdk9dRlIf0E95vcmNVc6nSAXgH5JQhE+p3DyvwIDAQAB
AoGBAIZldIRkP4Z0n2+j9OJQQUS6Wl7AjlyJDAc6cxhE0GOUzG+S1foVx6f92ZaC
2wLoha75zp691fkQuLWRnXu7nk9QwxQdOppKijIPHdL2cYtUc9UCedN5rExjpcOP
4Hjwf17YOxK2J0zzmG1djTBB47BKGUedSQ7E1QxGcrESS2XxAkEA+6ey2jy8etWi
QmCdJJIxXwKRVHCmt5LVwj+IOk/u3sr1AGfBm7spKGU3boCiFt4FmjGMax7B9r/e
zPaMb34guwJBAMIZX7Vv5gfjvWtgp6pyE/UkjRSOKBpuy9gyiqtLBJwehj/qsBqr
O6tFmjMFiudVusnVSrEFGAPLV52xf0U4580CQQDkEQ1UH2spX2dYBLslo6A+3NLc
1eMhx18WVgGd50cyfnkfzuh1vF8GjwR3jvhXBQvKvFDn284pU6YV1vNbL9F1AkEA
o2CwSwyRV3q+6i9Fchbr7aCCkBbIctdoBeclCeHvU2nuHsbwzMHtS9EeZmv365kh
zNoYMMDU4fy7FyVct2ua0QJASXtIwYKZ2CAP+lAQqfh+knRRqtqdLt4Lt0mpML5m
UtsECS8frKeF3mynXfsyRkvC8F2WFiJVJ3+D+y3zYNGlZg==
-----END RSA PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)
更新:在低级别握手数据包似乎是相同的,除了该random[32]字段使这更奇怪.
ssldump -a -A -H -i lo两种情况的SSL dump()都可以在这里找到:
http://pastebin.com/YuC7d8zg(不是好的情况)
我需要对python脚本进行以下两个调整,以使其适用于导出密码套件:
PROTOCOL = "sslv23"
...
print "[i] Initializing context ..."
ctx = M2Crypto.SSL.Context(protocol=PROTOCOL, weak_crypto=True)
ctx.load_cert_chain(certchainfile=CERTFILE, keyfile=KEYFILE)
ctx.set_options(M2Crypto.m2.SSL_OP_ALL)
ctx.set_tmp_rsa(M2Crypto.RSA.gen_key(512, 65537))
ctx.set_cipher_list("ALL")
Run Code Online (Sandbox Code Playgroud)
那是:
set_tmp_rsa().这是必需的,因为使用导出密码时,提供的(1024位)RSA密钥仅用于身份验证(签名),而临时的,导出残缺的512位RSA密钥用于机密性(加密).OpenSSL要求您在上下文中设置此密钥(请参阅SSL_set_tmp_rsa()的文档).古怪的是,它也适用于的SSLv2-only模式(使用-ssl2上openssl s_client进行测试时)不设置一个临时的RSA密钥(调用set_tmp_rsa脚本注释掉).我不知道为什么.
通常,一些密码套件需要将特殊键添加到上下文中,例如使用DH(组参数)或ECDH(曲线)的套件.要准确了解每个密码套件的用途,openssl ciphers -v可以很有见地,例如:
% openssl ciphers -v EXPORT
EXP-EDH-RSA-DES-CBC-SHA SSLv3 Kx=DH(512) Au=RSA Enc=DES(40) Mac=SHA1 export
EXP-EDH-DSS-DES-CBC-SHA SSLv3 Kx=DH(512) Au=DSS Enc=DES(40) Mac=SHA1 export
EXP-ADH-DES-CBC-SHA SSLv3 Kx=DH(512) Au=None Enc=DES(40) Mac=SHA1 export
EXP-DES-CBC-SHA SSLv3 Kx=RSA(512) Au=RSA Enc=DES(40) Mac=SHA1 export
EXP-RC2-CBC-MD5 SSLv3 Kx=RSA(512) Au=RSA Enc=RC2(40) Mac=MD5 export
EXP-RC2-CBC-MD5 SSLv2 Kx=RSA(512) Au=RSA Enc=RC2(40) Mac=MD5 export
EXP-ADH-RC4-MD5 SSLv3 Kx=DH(512) Au=None Enc=RC4(40) Mac=MD5 export
EXP-RC4-MD5 SSLv3 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export
EXP-RC4-MD5 SSLv2 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export
Run Code Online (Sandbox Code Playgroud)
编辑重新回答有关DSS密码套件的问题:
DSS/DSA密码套件需要DH参数,当然还有基于DSS/DSA的服务器证书,而不是(仅)RSA密码.这不仅适用于导出密码套件,也适用于使用DSS/DSA实现真实性的所有套件.DSS/DSA只能用于签名,而不能用于加密,以便允许导出到不受信任的国家/地区.由于DSS/DSA只能用于签名,因此需要短暂的Diffie-Hellman密钥交换来建立共享会话密钥.这就是密码套件中的EDH所代表的含义.要设置DH参数,您可以使用OpenSSL SSL_set_tmp_dh() API 的M2Crypto等效项.
请注意,OpenSSL允许将RSA和DSA/DSS证书/密钥对加载到同一SSL上下文中.