Skip to content

Tutorial 6: Adding Certificates

Artur Mrowca edited this page Jul 2, 2017 · 3 revisions

Tutorial 6 - Adding certificates

Certificates are needed for authentication. For this a fixed hierarchy of Certification Authorities is required to verify the protocol. Our hierarchy contains three roots CAEnum.CA_L1, CAEnum.CA_L2, CAEnum.CA_L3. Each root has subauthorities e.g. CAEnum.CA_L1 has CAEnum.CA_L11, CAEnum.CA_L12, CAEnum.CA_L13 and CAEnum.CA_L3 has CAEnum.CA_L31, CAEnum.CA_L32, CAEnum.CA_L33 and CAEnum.CA_L31 has children CAEnum.CA_L311, CAEnum.CA_L312 and CAEnum.CA_L313. With this certificate verification is possible. For verification root certificates are required and on the otherhand certificates are required.

1. Generating certificates

To generate certificates the following steps are required.

1.1. Add a certificate manager

First, you need to edit your main_test.py by adding the following lines of code at the beginning:

GeneralSpecPreset().certificate_manager = api.create_cert_manager()

FYI: To add a custom CA Hierarchy look at the CAHierarchy class and reimplement your version of it. Then, you can pass it as an argument to the create_cert_manager function. E.g.

myCA = MyCAHierarchy()
GeneralSpecPreset().certificate_manager = api.create_cert_manager(myCA)

1.2. Use certification structure

Next, a certificate from a custom CA can be created. In this example we create a certificate from Certification Authority CA_L311 which means that the root certificates of all layers 311, 31 and 3 are required to verify this certificate. This certificate is created at any point in the code using the following function (as GeneralSpecPreset() is a Singleton object). To generate type:

[certificate, root_certificates_to_verify_this_certificate, priv_key] = GeneralSpecPreset().certificate_manager.generate_valid_ecu_cert(self._ecu_id, CAEnum.CA_L311, 0, float('inf'))

The object certificate is now a certificate for the ecu with self._ecu_id and can be verified by having the root certificates given in root_certificates_to_verify_this_certificate. Also, each certificate has a public key which can encrypt or decrypt stuff (and is accessible as parameter of certificate). The corresponding private key is priv_key. Our protocol is valid from time t=0 to time t=infinity. But, when set differently can time out of course. Next, to verify this certificate we can use the following function:

certificate_valid = encryption_tools.certificate_trustworthy(certificate, root_certificates_to_verify_this_certificate, self.sim_env.now)

This function returns True if the certificate can be verified with the certificates given in root_certificates_to_verify_this_certificate and False otherwise (i.e. if the certificate is wrong or timed out or if the wrong root certificates are present).

1.3. Distributing certificates

To send certificates a good option is to set the certificates in the init function of each communication module. Thus, e.g. we add the following to the init function:

[certificate, root_certificates_to_verify_this_certificate, priv_key] = GeneralSpecPreset().certificate_manager.generate_valid_ecu_cert(self._ecu_id, CAEnum.CA_L311, 0, float('inf'))
self._my_certificate = certificate
self.my_root_certificates = root_certificates_to_verify_this_certificate

Next, we want to send our certificate to each other ECU (which have the same list of root certificates as we have). Thus, we add the following to the send_msg function:

'''Send my certificate to the other ECUs ''' 
message_to_send = SegData([message.get(), self.my_certificate],  50)

This certificate is received by another ECU. If it has the right root certificates it can verify this protocol, which is the case in our example as they all have L311 as certificate authority. Thus, we can add the following in the receive function

''' receive and verify certificate '''

[received_message, received_certificate] = message_data.get()
# verify certificate - which works here as they all have the same CA authority that signed the certificate
certificate_valid = encryption_tools.certificate_trustworthy(received_certificate, self.my_root_certificates, self.sim_env.now)

Another way to distribute which ECU gets which certificates is to use singleton objects. If you need support doing this you can gladly contact us. Or you can use the function generate_valid_ecu_cert to create an empty certificate with the same CA_L... which is also able to verify a certificate (similar to our example above)

1.4. Using further concepts - so far this is really just a fraction of our framework

Further concepts such as MAC, compressed messages or timestamps are also implemented. Please check the implementations of our security protocols to see how they work. They are all implemented in the encryption_tools module!

The most important part of our simulator however, is the concept of applying individual timeouts that were measured by us depending on algorithms and sizes of messages (that change after encryption e.g.) The concept and possibilities of our simulator in those terms will be described in the following tutorials. E.g. you can add your own timeouts that are used in the simulator. Also, we provide a pretty neat GUI which however, requires some steps to be applicable (maybe I will add this at a later point, depending on feedback and requests).

This example is implemented in Tutorial6AddCertificates. The code can be found on Github