From 6a83c0cd7dda6bb19e67d16316a38dae954c2f72 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Thu, 28 Jun 2012 17:50:05 -0400 Subject: [PATCH] Added testing key, cleaned up some code, added ext conf file --- ca/sni_challenge/testing.key | 27 +++++++++++++ ca/sni_challenge/verify_sni_challenge.py | 16 ++++---- webserver/choc_cert_extensions.cnf | 16 ++++++++ webserver/sni_challenge.py | 48 +++++++++++++++--------- 4 files changed, 82 insertions(+), 25 deletions(-) create mode 100644 ca/sni_challenge/testing.key create mode 100644 webserver/choc_cert_extensions.cnf diff --git a/ca/sni_challenge/testing.key b/ca/sni_challenge/testing.key new file mode 100644 index 000000000..bf83beab6 --- /dev/null +++ b/ca/sni_challenge/testing.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA4INAzUJea4/7KmYQWZJiKnxQ07IWASrgmmX3GwzY62W4WaEh +09p+vYO6yHFXzAa7Jelq4VxECsXzCfBzU72XNlTRup/kpy3zlgO4FzhhyuiOXqAb +m/ocLIXYSSI9nwI5YbJxNIPMNrd2vlaqy9O9km1rXyMzwTih1V1R82qP/xbarFBb +tE3SopmGrKv3jDrUy86AE4zjvzKBDobNMz4iV72B7xoecYq1I2grMsdoOUi0dUBc +bii7v8Ob4BKH0TWU5I6JmQkv59eS5JVL1mrnoACXgOdEfnO1F42S4qbjMyra+Gg/ +A+2XnEq2Z7hakIr1BInqDqZ9E7ffb1vNNzttyQIDAQABAoIBAQCg1OXDJNxG6anf +waXMxNSV4uB0BotE4tZrRMg0FIwAdaoOayO0hD1uvcM8fBWNDvVaP1BViKcloJBu +elXjk1mTjkeADbLbIEvzF071M2q61MXIe6HLpuwv6OH74g+KrSk2F4KJQDE2sU7b +I3LO+SxAjSnxyWH19P/ZvTRLz/a/oOPH3YjCuSKZSLZdNwS9L5xJ8/ScYeawGFOx +7CEF1QIRiz14q/TXF93U4iAFtj7Awz1yepd2bQ9gYbJpiUK1kWa3rPcmJLL/tGpQ +HgONEMn4SxxrpX+/O+HnrusxWQhsgjt1iWUOjJIvvONqa5kiKXhjMURMm6BC2046 +pwWy7VwBAoGBAPrRKH7ZeGPERv6TZILlkv3x/yKd/O0RP0JdGZyurkBzD+so61gc +qci+STOFlq5j+kqPnfYVhETsBsuMlwqKIHbJdinn9EHopy8wyuAHatQqHN2mWZ5V +EsGCfZILuIaYM1uTejqF/u2PRXDZdWPta9B7dhDXaXxvPSNXVAG1FlFhAoGBAOUm +8WsKrXIVVZvkmN3pWlXfJwhkn3+UG+yayYtque9smXDNETvg0QSUaIKuZj+blSLI +V2xtE6uleERpDjwiLVOgA/FlgZZxnVkZXUz4633I9pEuq1Zv5ZodSrQr0dg5R/Ap +B/V8ax2r1Y2Uosh/HmMhZirYck4EA/zc6jHshi1pAoGBAIm0+HTc1ZqBEzGGnzK2 +9QN0ME5DS7ClPYQkNYGu7oD4K49DQiN4aUeMIgilmdtZjPwO6f1IRvzIUdrD79Gb +kMNnTPcpIRRmthPUyC5EJEUkcgDH6oBh2RBhoqviv4c2XUw0JnGnTBYGCWwyGJ+q +pP0sK+CHRKVLNdgHhFoDoKNBAoGAdOVg0lIoGMJ5YYVD1jBsPNIRf16VXueXNyPf +HJfdMh4cSEbUO8970PJEPiXpUxlzAsNglZcvKajHqV5OPK7SoI5IdKRrbuuWcRVX +WyTAPPJ/laBRF08NuYinyzFvYvYVlJXZ0Ykeu4wk7IyeXdk7DybCj6jK5rF1t1Ca +x8z4xcECgYEAvAvGL6b1fQkF1ihqVFqnQGpRGEef2POE0fnj13i+RAVWUm9k3b45 +6losFlqxSNjpVxl5kFTGZcEh2UYqAB+fT7IwR/5IX6i+hXIv5U29Ng6BVNjvu2is +tijv/tSN07UvBZ4cFgZUw00aQ4hshCp95I0zYCwTtTIOgSRCJWQwUXY= +-----END RSA PRIVATE KEY----- diff --git a/ca/sni_challenge/verify_sni_challenge.py b/ca/sni_challenge/verify_sni_challenge.py index b04248028..b0312d3bb 100644 --- a/ca/sni_challenge/verify_sni_challenge.py +++ b/ca/sni_challenge/verify_sni_challenge.py @@ -12,10 +12,10 @@ def check(one, two, three, four, five): def byteToHex(byteStr): return ''.join(["%02X" % ord(x) for x in byteStr]).strip() -def check_challenge_value(ext_value, sharedSecret): +def check_challenge_value(ext_value, r): s = ext_value[0:S_SIZE] mac = ext_value[S_SIZE:] - expected_mac = hmac.new(sharedSecret, str(s), hashlib.sha256).digest() + expected_mac = hmac.new(r, str(s), hashlib.sha256).digest() #print "s: ", byteToHex(s) #print "mac: ", byteToHex(mac) @@ -27,8 +27,8 @@ def check_challenge_value(ext_value, sharedSecret): return True return False -def verify_challenge(address, sharedSecret, encryptedValue): - sni_name = byteToHex(encryptedValue[0]) + ".com" +def verify_challenge(address, r, nonce): + sni_name = nonce + ".chocolate" context = M2Crypto.SSL.Context() context.set_allow_unknown_ca(True) @@ -49,23 +49,25 @@ def verify_challenge(address, sharedSecret, encryptedValue): if sni_support.get_nid(ext.x509_ext) == 0: - valid = check_challenge_value(sni_support.get_unknown_value(ext.x509_ext), sharedSecret) + valid = check_challenge_value(sni_support.get_unknown_value(ext.x509_ext), r) if valid: return True, "Challenge completed successfully" else: return False, "Certificate extension does not check out" + return False, "Chocolate extension not included in certificate" def main(): #Testing the example sni_challenge from Crypto.PublicKey import RSA - testkey = RSA.importKey(open("/home/james/Documents/apache_choc/testing.key").read()) + nonce = "nonce" + testkey = RSA.importKey(open("testing.key").read()) #the second parameter is ignored #https://www.dlitz.net/software/pycrypto/api/current/ encryptedValue = testkey.encrypt('0x12345678', 0) - valid, response = verify_challenge("127.0.0.1", '0x12345678', encryptedValue) + valid, response = verify_challenge("127.0.0.1", '0x12345678', nonce) print response if __name__ == "__main__": diff --git a/webserver/choc_cert_extensions.cnf b/webserver/choc_cert_extensions.cnf new file mode 100644 index 000000000..5cba2c49d --- /dev/null +++ b/webserver/choc_cert_extensions.cnf @@ -0,0 +1,16 @@ +# +# OpenSSL configuration file. +# + +# Extra OBJECT IDENTIFIER info: +oid_section = new_oids + +[ new_oids ] +choc=1.3.3.7 + + +[ v3_ca ] +basicConstraints = CA:TRUE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +1.3.3.7=DER:C15B2E9D8F49A16C57A66F9E07C18C0B524183C427dae3a76c9c5945ff91c27d28eec5a4cc8e2e42a274f7de42d079bfe413171e diff --git a/webserver/sni_challenge.py b/webserver/sni_challenge.py index 3ae0f1d74..eef42cd75 100644 --- a/webserver/sni_challenge.py +++ b/webserver/sni_challenge.py @@ -10,34 +10,41 @@ from shutil import move from os import remove, close CHOC_DIR = "/home/james/Documents/apache_choc/" +#CHOC_KEY = "../ca/sni_challenge/testing.key" CHOC_KEY = CHOC_DIR + "testing.key" SERVER_BASE = "/etc/apache2/" CHOC_CERT = CHOC_DIR + "choc.crt" CSR = CHOC_DIR + "choc.csr" -CHOC_CERT_CONF = CHOC_DIR + "choc_cert_extensions.cnf" +CHOC_CERT_CONF = "choc_cert_extensions.cnf" APACHE_CHALLENGE_CONF = CHOC_DIR + "choc_sni_cert_challenge.conf" S_SIZE = 20 def findApacheConfigFile(): - return CHOC_DIR + "demo_apache.conf" + #return CHOC_DIR + "demo_apache.conf" + #This needs to be fixed to account for multiple httpd.conf files try: - p = subprocess.check_output(['find', '/', '-name', '"httpd.conf"'], stderr=open("/dev/null")) + p = subprocess.check_output(["sudo", "find", "/", "-name", "httpd.conf"], stderr=open("/dev/null")) + p = p[:len(p)-1] + print "Apache Config: ", p + return p except subprocess.CalledProcessError, e: - print "Not found" + print "httpd.conf not found" + print "Please include .... in the conf file" + return None -def modifyApacheConfig(mainConfig, nonce, servername, ip_addr): +def modifyApacheConfig(mainConfig, nonce, ip_addr): configText = " \n \ \n \ -Servername " + nonce + "-choc." + servername + " \n \ +Servername " + nonce + ".chocolate \n \ UseCanonicalName on \n \ \n \ LimitRequestBody 1048576 \n \ \n \ -Include options-ssl.conf \n \ +Include " + CHOC_DIR + "options-ssl.conf \n \ SSLCertificateFile " + CHOC_CERT + " \n \ SSLCertificateKeyFile " + CHOC_KEY + " \n \ \n \ -DocumentRoot " + CHOC_DIR + "virtual_server/ \n \ +DocumentRoot " + CHOC_DIR + "challenge_page/ \n \ \n \ " @@ -49,14 +56,18 @@ DocumentRoot " + CHOC_DIR + "virtual_server/ \n \ # Need to add NameVirtualHost IP_ADDR def checkForApacheConfInclude(mainConfig): searchStr = "Include " + APACHE_CHALLENGE_CONF - conf = open(mainConfig, 'r+') + #conf = open(mainConfig, 'r+') + conf = open(mainConfig, 'r') flag = False for line in conf: if line.startswith(searchStr): flag = True break if not flag: - conf.write(searchStr) + #conf.write(searchStr) + process = subprocess.Popen(["echo", "\n" + searchStr], stdout=subprocess.PIPE) + subprocess.check_output(["sudo", "tee", "-a", mainConfig], stdin=process.stdout) + process.stdout.close() conf.close(); @@ -69,12 +80,12 @@ def createChallengeCert(ext): def generateExtension(challengeValue): rsaPrivKey = RSA.importKey(open(CHOC_KEY).read()) - sharedSecret = rsaPrivKey.decrypt(challengeValue) - print sharedSecret + r = rsaPrivKey.decrypt(challengeValue) + print r s = Random.get_random_bytes(S_SIZE) #s = "0xDEADBEEF" - extHMAC = hmac.new(sharedSecret, str(s), hashlib.sha256) + extHMAC = hmac.new(r, str(s), hashlib.sha256) return byteToHex(s) + extHMAC.hexdigest() def byteToHex(byteStr): @@ -95,24 +106,25 @@ def updateCertConf(value): move(CHOC_CERT_CONF + ".tmp", CHOC_CERT_CONF) def apache_restart(): - subprocess.call(["/etc/init.d/apache2", "reload"]) + subprocess.call(["sudo", "/etc/init.d/apache2", "reload"]) #main call -def perform_sni_cert_challenge(encryptedValue): +def perform_sni_cert_challenge(encryptedValue, nonce): ext = generateExtension(encryptedValue) createChallengeCert(ext) #Need to decide the form of nonce - modifyApacheConfig(findApacheConfigFile(), "Nonce", "choc_sni_challenge.com", "127.0.0.1") - #apache_restart() + modifyApacheConfig(findApacheConfigFile(), nonce, "127.0.0.1") + apache_restart() def main(): + testkey = RSA.importKey(open(CHOC_KEY).read()) #the second parameter is ignored #https://www.dlitz.net/software/pycrypto/api/current/ encryptedValue = testkey.encrypt('0x12345678', 0) - perform_sni_cert_challenge(encryptedValue) + perform_sni_cert_challenge(encryptedValue, "nonce") if __name__ == "__main__": main()