Home | History | Annotate | Download | only in utils
      1 #!/usr/bin/env python
      2 #
      3 # Copyright (C) 2016 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the 'License');
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an 'AS IS' BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 import random
     17 
     18 from OpenSSL import crypto
     19 from Crypto.PublicKey import RSA
     20 
     21 class Certificate(object):
     22     cert = None
     23     key = None
     24     def __init__(self, cert, key):
     25         self.cert = cert
     26         self.key = key
     27 
     28     def cert_pem(self):
     29         return crypto.dump_certificate(crypto.FILETYPE_PEM, self.cert)
     30 
     31     def key_pem(self):
     32         return crypto.dump_privatekey(crypto.FILETYPE_PEM, self.key)
     33 
     34     def save_to_file(self, path):
     35         with open(path, "w") as f:
     36             f.write(self.cert_pem())
     37             f.write(self.key_pem())
     38 
     39     def save_cert_to_file(self, path):
     40         with open(path, "w") as f:
     41             f.write(self.cert_pem())
     42 
     43     @staticmethod
     44     def from_file(path):
     45         with open(path) as f:
     46             data = f.read()
     47             cert = crypto.load_certificate(crypto.FILETYPE_PEM, data)
     48             key = crypto.load_privatekey(crypto.FILETYPE_PEM, data)
     49             return Certificate(cert, key)
     50 
     51     @staticmethod
     52     def create(cn, issuer=None, key=None, keysize=2048, digest="sha256",
     53             notBefore="20150101000000+0000", notAfter="20300101000000+0000",
     54             additional_extensions=None):
     55         if key is None:
     56             key = crypto.PKey()
     57             key.generate_key(crypto.TYPE_RSA, keysize)
     58 
     59         cert = crypto.X509()
     60         cert.set_pubkey(key)
     61         cert.set_version(2)
     62         cert.set_serial_number(random.randint(0, 2**20))
     63 
     64         cert.set_notBefore(notBefore)
     65         cert.set_notAfter(notAfter)
     66         cert.get_subject().CN = cn
     67         cert.set_issuer(cert.get_subject() if issuer is None else issuer.cert.get_subject())
     68         # Add the CA=True basic constraint
     69         basicContraints = crypto.X509Extension("basicConstraints", True, "CA:TRUE")
     70         cert.add_extensions([basicContraints])
     71         if additional_extensions is not None:
     72             cert.add_extensions(additional_extensions)
     73 
     74         signing_key = key if issuer is None else issuer.key
     75         cert.sign(signing_key, digest)
     76 
     77         return Certificate(cert, key)
     78 
     79 if __name__ == "__main__":
     80     # Generate test certificates.
     81     a = Certificate.create("Root A")
     82     a_sha1 = Certificate.create("Root A", key=a.key, digest="sha1")
     83     b = Certificate.create("Root B")
     84     a_to_b = Certificate.create("Root A", b, a.key)
     85     b_to_a = Certificate.create("Root B", a, b.key)
     86     leaf1 = Certificate.create("Leaf", a)
     87     intermediate_a = Certificate.create("intermediate", a)
     88     intermediate_b = Certificate.create("intermediate", b, intermediate_a.key)
     89     leaf2 = Certificate.create("Leaf 2", intermediate_a)
     90 
     91     # Save test certificates.
     92     a.save_cert_to_file("a.pem")
     93     a_sha1.save_cert_to_file("a_sha1.pem")
     94     b.save_cert_to_file("b.pem")
     95     a_to_b.save_cert_to_file("a_to_b.pem")
     96     b_to_a.save_cert_to_file("b_to_a.pem")
     97     leaf1.save_cert_to_file("leaf1.pem")
     98     leaf2.save_cert_to_file("leaf2.pem")
     99     intermediate_a.save_cert_to_file("intermediate_a.pem")
    100     intermediate_b.save_cert_to_file("intermediate_b.pem")
    101