Skip to content

Instantly share code, notes, and snippets.

@serac
Created September 9, 2016 13:10
Show Gist options
  • Save serac/4b6a9f5e382d0c29134839f0b5cd701a to your computer and use it in GitHub Desktop.
Save serac/4b6a9f5e382d0c29134839f0b5cd701a to your computer and use it in GitHub Desktop.
Convert OpenSSL TLS Cipher String to Java Cipher List
#!/usr/bin/env python
import sys
from os.path import basename
from subprocess import Popen, PIPE
"""Map of OpenSSL symmetric cipher names to cipher/block size tuples."""
CIPHERS={
'AES': ('AES', 128),
'AES128': ('AES', 128),
'AES256': ('AES', 256),
'3DES': ('3DES_EDE', 112),
'DES': ('3DES_EDE', 112),
'RC4': ('RC4', 128),
'SEED': ('SEED', 128),
'CAMELLIA128': ('CAMELLIA', 128),
'CAMELLIA256': ('CAMELLIA', 256),
'IDEA': ('IDEA', 128)
}
"""Map of OpenSSL key exchange protocol names to corresponding Java name."""
KX_PROTOS={
'AECDH':'ECDH_anon',
'ADH':'DH_anon',
'DH':'DH',
'DHE':'DHE',
'ECDH':'ECDH',
'ECDHE':'ECDHE',
'EDH':'EDH',
'PSK':'PSK',
'RSA':'RSA',
'SRP':'SRP'
}
"""Authentication protocol names."""
AUTH_PROTOS=(
'DSS',
'ECDSA',
'PSK',
'RSA',
'SRP'
)
"""Digest algorithm names."""
DIGESTS=(
'MD5',
'SHA',
'SHA256',
'SHA384'
)
class JavaCipher(object):
"""TLS cipher suite descriptor."""
def __init__(self):
self.proto = 'TLS'
self.kx = 'RSA'
self.auth = 'RSA'
self.enc = 'AES'
self.enc_size = 128
self.enc_pad = 'CBC'
self.mac = 'SHA'
def __str__(self):
if self.kx == self.auth:
s = '{0.proto}_{0.kx}_WITH_{0.enc}'.format(self)
else:
s = '{0.proto}_{0.kx}_{0.auth}_WITH_{0.enc}'.format(self)
if self.enc != '3DES_EDE' and self.enc != 'SEED':
s += '_{0.enc_size}'.format(self)
if self.enc != 'RC4':
s += '_{0.enc_pad}'.format(self)
return s + '_{0.mac}'.format(self)
def parse(cipher_spec):
"""Parse an OpenSSL TLS cipher specification into a JavaCipher object."""
parts = cipher_spec.split('-')
jc = JavaCipher()
enc_idx = 0
if parts[0] in KX_PROTOS.keys():
jc.kx = KX_PROTOS[parts[0]]
if parts[1] in AUTH_PROTOS:
jc.auth = parts[1]
enc_idx = 2
else:
jc.auth = jc.kx
enc_idx = 1
(jc.enc, jc.enc_size) = CIPHERS[parts[enc_idx]]
if parts[enc_idx+1] in DIGESTS:
jc.mac = parts[enc_idx+1]
else:
jc.enc_pad = parts[enc_idx+1][0:3]
jc.mac = parts[enc_idx+2]
return jc
if len(sys.argv) < 2:
print """USAGE: {0} List:of:OpenSSL:ciphers\nEXAMPLE:
{0} 'EECDH+AESGCM:ECDHE+AESGCM:HIGH:!MD5:!RC4:!aNULL'
""".format(basename(sys.argv[0]))
sys.exit(0)
ossl_cmd = "openssl ciphers '%s'" % sys.argv[1]
output = Popen(ossl_cmd, shell=True, stdout=PIPE).stdout.readlines()
ciphers = output[0].strip().split(':')
for cipher in ciphers:
print parse(cipher)
@serac
Copy link
Author

serac commented Sep 9, 2016

NOTE: Requires openssl to be on your path.

Example output:

marvin@eiger:~$ ossl-ciphers-to-java.py 'EECDH+AESGCM:ECDHE+AESGCM:HIGH:!MD5:!RC4:!aNULL'
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_SRP_DSS_WITH_AES_128_256_CBC
TLS_SRP_RSA_WITH_AES_128_256_CBC
TLS_SRP_WITH_AES_128_256_CBC
TLS_DH_DSS_WITH_AES_256_GCM_SHA384
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
TLS_DH_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
TLS_DH_RSA_WITH_AES_256_CBC_SHA256
TLS_DH_DSS_WITH_AES_256_CBC_SHA256
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
TLS_DH_RSA_WITH_AES_256_CBC_SHA
TLS_DH_DSS_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_PSK_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_SRP_DSS_WITH_AES_128_128_CBC
TLS_SRP_RSA_WITH_AES_128_128_CBC
TLS_SRP_WITH_AES_128_128_CBC
TLS_DH_DSS_WITH_AES_128_GCM_SHA256
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
TLS_DH_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_DH_RSA_WITH_AES_128_CBC_SHA256
TLS_DH_DSS_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
TLS_DH_RSA_WITH_AES_128_CBC_SHA
TLS_DH_DSS_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA
TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
TLS_PSK_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_SRP_DSS_WITH_3DES_EDE_EDE_CBC
TLS_SRP_RSA_WITH_3DES_EDE_EDE_CBC
TLS_SRP_WITH_3DES_EDE_EDE_CBC
TLS_EDH_RSA_WITH_3DES_EDE_CBC_SHA
TLS_EDH_DSS_WITH_3DES_EDE_CBC_SHA
TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_PSK_WITH_3DES_EDE_EDE_CBC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment