config docs
[sfa.git] / util / sec / certgen.py
1 #
2 # certgen.py
3 #
4 # Copyright (C) Martin Sjogren and AB Strakt 2001, All rights reserved
5 #
6 # $Id: certgen.py,v 1.2 2004/07/22 12:01:25 martin Exp $
7 #
8 """
9 Certificate generation and validation module.
10 """
11
12 from OpenSSL import crypto
13 import time, calendar, datetime
14
15 TYPE_RSA = crypto.TYPE_RSA
16 TYPE_DSA = crypto.TYPE_DSA
17
18 def createKeyPair(type, bits):
19     """
20     Create a public/private key pair.
21
22     Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA
23                bits - Number of bits to use in the key
24     Returns:   The public/private key pair in a PKey object
25     """
26     pkey = crypto.PKey()
27     pkey.generate_key(type, bits)
28     return pkey
29
30 def createCertRequest(pkey, name, digest="md5"):
31     """
32     Create a certificate request.
33
34     Arguments: pkey   - The key to associate with the request
35                digest - Digestion method to use for signing, default is md5
36                **name - The name of the subject of the request, possible
37                         arguments are:
38                           C     - Country name
39                           ST    - State or province name
40                           L     - Locality name
41                           O     - Organization name
42                           OU    - Organizational unit name
43                           CN    - Common name
44                           emailAddress - E-mail address
45     Returns:   The certificate request in an X509Req object
46     """
47     req = crypto.X509Req()
48     subj = req.get_subject()
49     for (key,value) in name.items():
50         setattr(subj, key, value)
51     req.set_pubkey(pkey)
52     req.sign(pkey, digest)
53     return req
54
55 def createCertificate(req, (issuerCert, issuerKey), serial, (notBefore, notAfter), extensions=[], digest="md5"):
56     """
57     Generate a certificate given a certificate request.
58
59     Arguments: req        - Certificate reqeust to use
60                issuerCert - The certificate of the issuer
61                issuerKey  - The private key of the issuer
62                serial     - Serial number for the certificate
63                notBefore  - Timestamp (relative to now) when the certificate
64                             starts being valid
65                notAfter   - Timestamp (relative to now) when the certificate
66                             stops being valid
67                digest     - Digest method to use for signing, default is md5
68     Returns:   The signed certificate in an X509 object
69     """
70     cert = crypto.X509()
71     cert.set_serial_number(serial)
72     cert.gmtime_adj_notBefore(notBefore)
73     cert.gmtime_adj_notAfter(notAfter)
74     cert.set_issuer(issuerCert.get_subject())
75     cert.set_subject(req.get_subject())
76     cert.set_pubkey(req.get_pubkey())
77     if extensions:
78         extList = []
79         for name, critical, value in extensions:
80             ext = crypto.X509Extension (name, critical, value)
81             extList.append(ext)
82         cert.add_extensions(extList)
83     cert.sign(issuerKey, digest)
84     return cert
85
86
87 #checks if a certificate is valid in terms of validity periods    
88 def check_valid(usercert):
89     """
90     Method that ensures the issuer cert has
91     valid, not_before and not_after fields
92     """
93     valid = True
94     before_time = usercert.get_not_before()
95     after_time = usercert.get_not_after()
96     before_tuple = time.strptime(str(before_time), "%b %d %H:%M:%S %Y %Z")
97     after_tuple = time.strptime(str(after_time), "%b %d %H:%M:%S %Y %Z")
98     starts =  datetime.timedelta(seconds=calendar.timegm(before_tuple))
99     expires = datetime.timedelta(seconds=calendar.timegm(after_tuple))
100     now = datetime.timedelta(seconds=time.time())
101     time_delta = expires - now
102     
103     #cert has expired
104     if time_delta.days < 0:
105         valid = False
106     #cert is not yet valid
107     time_delta = now - starts
108     if time_delta.days < 0:   
109         valid = False
110
111     return valid