changeset 821:b767a45cec65

Generate keys and certificate using PyOpenSSL. This removes the dependency on make and the certtool program from GnuTLS.
author Martin Geisler <mg@daimi.au.dk>
date Sat, 12 Jul 2008 19:44:08 +0200
parents facc9f1f0bb1
children 4caf0ba0f517
files apps/generate-certificates apps/generate-certificates.py
diffstat 2 files changed, 97 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/apps/generate-certificates	Sat Jul 12 18:14:38 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-#!/usr/bin/make -f
-
-# Copyright 2007, 2008 VIFF Development Team.
-#
-# This file is part of VIFF, the Virtual Ideal Functionality Framework.
-#
-# VIFF is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License (LGPL) as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# VIFF is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
-# Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
-
-# This file is a Makefile which will generate private keys and TLS
-# certificates for the players. An extra key and certificate is made
-# for signing the other keys.
-#
-# Each player needs three files to create a TLS connection: the
-# certificate (player-X.cert), the private key (player-X.key), and the
-# CA certificate (ca.cert).
-
-# TODO: This should probably be rewritten in Python. The optimal
-# solution would be a rewrite that uses the Python GNUTLS bindings.
-
-# Default number of players. To generate keys and certificates for,
-# say, 5 players, simply add 'N=5' as a command line argument when you
-# run the Makefile.
-N = 3
-
-PLAYERS = $(addprefix player-, $(shell seq $N))
-KEYS = $(addsuffix .key, $(PLAYERS) ca)
-CERTS = $(addsuffix .cert, $(PLAYERS) ca)
-REQUESTS = $(addsuffix .request, $(PLAYERS) ca)
-CFGS = $(addsuffix .cfg, $(PLAYERS) ca)
-
-
-.PHONY: all
-all: $(CERTS)
-
-.PHONY: clean
-clean:
-	rm -f $(CERTS)
-	rm -f $(REQUESTS)
-	rm -f $(CFGS)
-
-.PHONY: distclean
-distclean: clean
-	rm -f $(KEYS)
-
-%.key:
-	certtool --generate-privkey --outfile $@
-
-player-%.cfg:
-	@echo 'cn = "VIFF Player $*"' > $@
-	@echo 'serial = $*' >> $@ # The player number is encoded here.
-	@echo 'expiration_days = 365' >> $@
-	@echo 'signing_key' >> $@
-	@echo 'encryption_key' >> $@
-
-player-%.request: player-%.cfg player-%.key
-	certtool --generate-request --template player-$*.cfg \
-	 --load-privkey player-$*.key --outfile $@
-
-player-%.cert: player-%.request player-%.cfg ca.cert ca.key
-	certtool --generate-certificate --template player-$*.cfg \
-	 --load-request player-$*.request \
-	 --load-ca-certificate ca.cert --load-ca-privkey ca.key \
-	 --outfile $@
-
-ca.cfg:
-	@echo 'cn = "VIFF Certificate Authority"' > $@
-	@echo 'expiration_days = 365' >> $@
-	@echo 'ca' >> $@
-	@echo 'cert_signing_key' >> $@
-
-
-ca.cert: ca.cfg ca.key
-	certtool --generate-self-signed --template ca.cfg \
-	         --load-privkey ca.key --outfile ca.cert
-
-.INTERMEDIATE: ca.cfg
-.PRECIOUS: %.key
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apps/generate-certificates.py	Sat Jul 12 19:44:08 2008 +0200
@@ -0,0 +1,97 @@
+#!/usr/bin/python
+
+# Copyright 2008 VIFF Development Team.
+#
+# This file is part of VIFF, the Virtual Ideal Functionality Framework.
+#
+# VIFF is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License (LGPL) as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# VIFF is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
+
+# This program will generate private keys and SSL/TLS certificates for
+# the players. An extra key and certificate is made for signing the
+# other keys.
+#
+# Each player needs three files to create a SSL/TLS connection: the
+# certificate (player-X.cert), the private key (player-X.key), and the
+# CA certificate (ca.cert).
+
+from OpenSSL import crypto
+from optparse import OptionParser
+
+parser = OptionParser()
+parser.add_option("-p", "--prefix",
+                  help="output filename prefix")
+parser.add_option("-k", "--key-size", type="int",
+                  help="key size")
+parser.add_option("-n", "--players", dest="n", type="int",
+                  help="number of players")
+
+parser.set_defaults(n=3, key_size=1024, prefix='player')
+
+(options, args) = parser.parse_args()
+
+
+def create_key(bits, type=crypto.TYPE_RSA):
+    """Create a public/private key pair."""
+    pk = crypto.PKey()
+    pk.generate_key(type, bits)
+    return pk
+
+def save_key(key, filename):
+    """Save a key as a PEM file."""
+    fp = open(filename, "w")
+    fp.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key))
+    fp.close()
+
+def create_cert_request(pk, common_name, digest="sha1"):
+    """Create a certificate request."""
+    req = crypto.X509Req()
+    subj = req.get_subject()
+    subj.CN = common_name
+
+    req.set_pubkey(pk)
+    req.sign(pk, digest)
+    return req
+
+def create_cert(req, issuer_cert, issuer_sk, serial, valid=365, digest="sha1"):
+    """Generate a certificate given a certificate request."""
+    cert = crypto.X509()
+    cert.set_serial_number(serial)
+    cert.gmtime_adj_notBefore(0)
+    cert.gmtime_adj_notAfter(valid * 60 * 60 * 24)
+    cert.set_issuer(issuer_cert.get_subject())
+    cert.set_subject(req.get_subject())
+    cert.set_pubkey(req.get_pubkey())
+    cert.sign(issuer_sk, digest)
+    return cert
+
+def save_cert(cert, filename):
+    """Save a certificate as a PEM file."""
+    fp = open(filename, "w")
+    fp.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
+    fp.close()
+
+ca_key = create_key(options.key_size)
+ca_req = create_cert_request(ca_key, "VIFF Certificate Authority")
+ca_cert = create_cert(ca_req, ca_req, ca_key, 0)
+
+save_key(ca_key, "ca.key")
+save_cert(ca_cert, "ca.cert")
+
+for i in range(1, options.n + 1):
+    key = create_key(options.key_size)
+    req = create_cert_request(key, "VIFF Player %d" % i)
+    cert = create_cert(req, ca_cert, ca_key, i)
+
+    save_key(key, "%s-%d.key" % (options.prefix, i))
+    save_cert(cert, "%s-%d.cert" % (options.prefix, i))