demo/secure_element/resources/generation_scripts/create_server_cert.py

1 from __future__ import print_function
2 import datetime
3 import traceback
4 import optparse
5 
6 from secure_element_common import *
7 
8 
9 
10 ''' ******************************************************************************************* '''
11 def create_server_cert(hostname):
12  print('\nLoading server CA CSR')
13  if not os.path.isfile(CREDENTIAL_PATH(SERVER_CSR_FILENAME)):
14  generate_server_csr(hostname)
15 
16  with open(CREDENTIAL_PATH(SERVER_CSR_FILENAME), 'rb') as f:
17  print(' Loading from ' + f.name)
18  server_csr = x509.load_pem_x509_csr(f.read(), crypto_be)
19 
20  if not server_csr.is_signature_valid:
21  raise RuntimeError('Server CA CSR has invalid signature.')
22 
23  print('\nLoading root CA key')
24  if not os.path.isfile(CREDENTIAL_PATH(ROOT_CA_KEY_FILENAME)):
25  raise Exception('Failed to find root CA key file, ' + ROOT_CA_KEY_FILENAME + '. Have you run the script: ca_create_root.py first?')
26 
27  with open(CREDENTIAL_PATH(ROOT_CA_KEY_FILENAME), 'rb') as f:
28  print(' Loading from ' + f.name)
29  root_ca_priv_key = serialization.load_pem_private_key(
30  data=f.read(),
31  password=None,
32  backend=crypto_be)
33 
34  print('\nLoading root CA certificate')
35  if not os.path.isfile(CREDENTIAL_PATH(ROOT_CA_CERT_FILENAME)):
36  raise Exception('Failed to find root CA certificate file, ' + ROOT_CA_CERT_FILENAME + '. Have you run the script: ca_create_root.py first?')
37 
38  with open(CREDENTIAL_PATH(ROOT_CA_CERT_FILENAME), 'rb') as f:
39  print(' Loading from ' + f.name)
40  root_ca_cert = x509.load_pem_x509_certificate(f.read(), crypto_be)
41 
42  # Create signer CA certificate
43  print('\nGenerating server certificate from CSR')
44  builder = x509.CertificateBuilder()
45  builder = builder.serial_number(random_cert_sn(16))
46  builder = builder.issuer_name(root_ca_cert.subject)
47  builder = builder.not_valid_before(datetime.datetime.now(tz=pytz.utc))
48  builder = builder.not_valid_after(builder._not_valid_before.replace(year=builder._not_valid_before.year + 10))
49  builder = builder.subject_name(server_csr.subject)
50  builder = builder.public_key(server_csr.public_key())
51  builder = add_extensions(
52  builder=builder,
53  authority_cert=root_ca_cert)
54  # Sign signer certificate with root
55  server_cert = builder.sign(
56  private_key=root_ca_priv_key,
57  algorithm=hashes.SHA256(),
58  backend=crypto_be)
59 
60  # Write server certificate to file
61  with open(CREDENTIAL_PATH(SERVER_CERT_FILENAME), 'wb') as f:
62  print(' Saving to ' + f.name)
63  f.write(server_cert.public_bytes(encoding=serialization.Encoding.PEM))
64 
65 
66  with open(CREDENTIAL_PATH(SERVER_CERT_CHAIN_FILENAME), 'wb') as dst:
67  print(' Saving certificate chain to ' + f.name)
68  with open(CREDENTIAL_PATH(ROOT_CA_CERT_FILENAME), 'rb') as src:
69  dst.write(src.read())
70  with open(CREDENTIAL_PATH(SERVER_CERT_FILENAME), 'rb') as src:
71  dst.write(src.read())
72 
73 
74  print('\nDone')
75 
76 
77 ''' ******************************************************************************************* '''
78 def generate_server_csr(hostname):
79  # Load or create a server cert key pair
80  print('\nLoading server cert key')
81  server_priv_key = load_or_create_key(SERVER_KEY_FILENAME)
82 
83  print('\nGenerating server CSR')
84 
85  name = x509.Name([
86  x509.NameAttribute(x509.oid.NameOID.ORGANIZATION_NAME, u'Example Inc'),
87  x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, unicode(hostname))
88  ])
89 
90  builder = x509.CertificateSigningRequestBuilder()
91  builder = builder.subject_name(name)
92  server_csr = builder.sign(
93  private_key=server_priv_key,
94  algorithm=hashes.SHA256(),
95  backend=crypto_be)
96 
97  # Save CSR
98  with open(CREDENTIAL_PATH(SERVER_CSR_FILENAME), 'wb') as f:
99  print(' Saving to ' + f.name)
100  f.write(server_csr.public_bytes(encoding=serialization.Encoding.PEM))
101 
102 
103 
104 ''' ******************************************************************************************* '''
105 def add_extensions(builder, public_key=None, authority_cert=None):
106  if public_key == None:
107  public_key = builder._public_key # Public key not specified, assume its in the builder (cert builder)
108 
109  builder = builder.add_extension(
110  x509.BasicConstraints(ca=True, path_length=0),
111  critical=True)
112 
113  builder = builder.add_extension(
114  x509.KeyUsage(
115  digital_signature=True,
116  content_commitment=False,
117  key_encipherment=False,
118  data_encipherment=False,
119  key_agreement=False,
120  key_cert_sign=True,
121  crl_sign=True,
122  encipher_only=False,
123  decipher_only=False),
124  critical=True)
125 
126  builder = builder.add_extension(
127  x509.SubjectKeyIdentifier.from_public_key(public_key),
128  critical=False)
129  subj_key_id_ext = builder._extensions[-1] # Save newly created subj key id extension
130 
131  if authority_cert:
132  # We have an authority certificate, use its subject key id
133  builder = builder.add_extension(
134  x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
135  authority_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)),
136  critical=False)
137  else:
138  # No authority cert, assume this is a CSR and just use its own subject key id
139  builder = builder.add_extension(
140  x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(subj_key_id_ext),
141  critical=False)
142 
143  return builder
144 
145 
146 
147 
148 
149 ''' ******************************************************************************************* '''
150 if __name__ == '__main__':
151  parser = optparse.OptionParser(description='Generates a server certificate for local testing')
152  parser.add_option('--hostname',
153  help="Required, Hostname of local testing server, typically this should be your computer's IP address. NOTE: You can also update your computer's 'hosts' file to use a domain")
154 
155  options, _ = parser.parse_args()
156 
157  if not options.hostname:
158  raise Exception('Must provide --hostname argument')
159 
160  try:
161  create_server_cert(options.hostname)
162  except Exception as e:
163  traceback.print_exc()
164  print(e)
165 
166