Copyright (C) 2015-16 Jaguar Land Rover This document is licensed under Creative Commons Attribution-ShareAlike 4.0 International. # CREATING RVI CERTIFICATES This document describes how to generate the necessary certificates, keys and credentials needed for RVI Core. The example certificates are used in (rvi_protocol.md)[rvi_protocol.md]. # STANDARDS USED [1] JSON Web Token RFC7519- JWT (link)[https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32]
[2] base64url - (link)[https://en.wikipedia.org/wiki/Base64)
[3] Transport Layer Security (TLS) - (link)[https://en.wikipedia.org/wiki/Transport_Layer_Security]
[4] X.509 Certificates - (link)[https://en.wikipedia.org/wiki/X.509]
For all examples below the following certificates are used: ## Sample root certificate The self signed root certificate used in the examples throughout this document was generated using the following commands: ```Shell # Create root key pair openssl genrsa -out insecure_root_key.pem 1024 # Create a self-signed root CA certificate, signed by the root key created above openssl req -x509 -new -nodes -key insecure_root_key.pem -days 365 -out insecure _root_cert.crt ``` The content of the sample ```insecure_root_key.pem``` private key file, which has no password protection, is: ``` -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDg5A1uZ5F36vQEYbMWCV4wY4OVmicYWEjjl/8YPA01tsz4x68i /NnlMNalqpGCIZ0AwqGI5DZAWWoR400L3SAmYD6sWj2L9ViIAPk3ceDU8olYrf/N wj78wVoG7qqNLgMoBNM584nlY4jy8zJ0Ka9WFBS2aDtB3Aulc1Q8ZfhuewIDAQAB AoGAfD+C7CxsQkSc7I7N0q76SuGwIUc5skmUe6nOViVXZwXH2Or55+qqt+VzsbO7 EJphk7n0ZR0wm/zKjXd3acaRq5j3fOyXip9fDoNj+oUKAowDJ9vub0NOPpU2bgb0 xDnDeR0BRVBOTWqrkDeDPBSxw5RlJunesDkamAmj4VXHHgECQQDzqDtaEuEZ7x7d kJKCmfGyP01s+YPlquDgogzAeMAsz17TFt8JS4RO0rX71+lmx7qqpRqIxVXIsR58 NI2Th7tRAkEA7Eh1C1WahLCxojQOam/l7GyE+2ignZYExqonOOvsk6TG0LcFm7W9 x39ouTlfChM26f8VYAsPxIrvsDlI1DDCCwJBAITmA8lzdrgQhwNOsbrugLg6ct63 kcuZUqLzgIUS168ZRJ1aYjjNqdLcd0pwT+wxkI03FKv5Bns6sGgKuhX3+KECQFm/ Z93HRSrTZpViynr5R88WpShNZHyW5/eB1+YSDslB1FagvhuX2570MRXxybys8bXN sxPI/9M6prI8AALBBmMCQD+2amH2Y9ukJy10WuYei943mrCsp1oosWjcoMADRCpj ZA2UwSzj67PBc5umDIAlhVRMX0zH/gLj54rfIkH5zLk= -----END RSA PRIVATE KEY----- ``` The root key above is checked in as ```priv/keys/insecure_root_key.pem```.
The content of the sample ```insecure_root_cert.crt``` file is: ``` -----BEGIN CERTIFICATE----- MIICUjCCAbugAwIBAgIJAMI080XZPsPUMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV BAYTAlVTMQ8wDQYDVQQIDAZPcmVnb24xETAPBgNVBAcMCFBvcnRsYW5kMQ8wDQYD VQQKDAZHRU5JVkkwHhcNMTUxMTI3MjMxMTQ0WhcNMTYxMTI2MjMxMTQ0WjBCMQsw CQYDVQQGEwJVUzEPMA0GA1UECAwGT3JlZ29uMREwDwYDVQQHDAhQb3J0bGFuZDEP MA0GA1UECgwGR0VOSVZJMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDg5A1u Z5F36vQEYbMWCV4wY4OVmicYWEjjl/8YPA01tsz4x68i/NnlMNalqpGCIZ0AwqGI 5DZAWWoR400L3SAmYD6sWj2L9ViIAPk3ceDU8olYrf/Nwj78wVoG7qqNLgMoBNM5 84nlY4jy8zJ0Ka9WFBS2aDtB3Aulc1Q8ZfhuewIDAQABo1AwTjAdBgNVHQ4EFgQU 4Sz8rAMA+dHymJTlZSkap65qnfswHwYDVR0jBBgwFoAU4Sz8rAMA+dHymJTlZSka p65qnfswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQDFOapf3DNEcXgp 1u/g8YtBW24QsyB+RRavA9oKcFiIaHMkbJyUsOergwOXxBYhduuwVzQQo9P5nR0W RdUfwtE0GuaiC8WUmjR//vKwakj9Bjuu73ldYj9ji9+eXsL/gtpGWTIlHeGugpFs mVrUm0lY/n2ilJQ1hzBZ9lFLq0wfjw== -----END CERTIFICATE----- ``` The root certificate above is checked in as ```priv/certificates/insecure_root_cert.crt```. **DO NOT USE THE KEYS AND CERTIFICATES ABOVE IN PRODUCTION!
ANY PRODUCTION KEYS SHOULD BE GENERATED BY THE ORGANIZATION AND BE 4096 BITS LONG.** ## Sample device certificate The sample device x.509 certificate, signed by the root certificate above, was generated with the following command: ```Shell # Create the device key. In production, increase the bit size to 4096+ openssl genrsa -out insecure_device_key.pem 1024 # Create a certificate signing request openssl req -new -key insecure_device_key.pem -out insecure_device_cert.csr # Sign the signing request and create the insecure_device_cert.crt file openssl x509 -req -days 365 -in insecure_device_cert.csr \ -CA insecure_root_cert.crt -CAkey insecure_root_key.pem \ -set_serial 01 -out insecure_device_cert.crt ``` The ```insecure_device_cert.csr``` intermediate certificate signing request can be deleted once the three steps above have been executed.
The content of the sample ```insecure_device_key.pem``` private key file, which has no password protection, is: ``` -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCbb4jPAESKxarj3NJsgfQbhfTHZAP9kmram2TFnkzlCRxq4wQx BDC0O85PAMgZou0armGGbOu0si4cpVRioerCQJXnMWx1MI+3GUktW5ijI3ui+tYC sMQZtjSBVNXFZdoyZU2lPVWITOMZOe8o9vJ5DcUmFj9b2xV9jQ19oh+2+QIDAQAB AoGAVCYV0rs6YEaTNbke0k+ocB4dXrTu1CCoaKEn9TS2PGiqUdOFOWQjWe/myS6L JhXmd0Ng2P2uvayY+jknbh5qkNeEgTDhXJlAjiXlCADYArhgib+evRHgKz7RLTjX tGklbmc7oECTEpjkchJC5XcJhXzHCIjroyOJvBuAVa+SeAECQQDNC+KW7fTKQpiG YNGIt5MxCMjRparLz0fWod9J9U56wrWzU9Rnb7h9iwzTEJUEcVl9z8rnUdWtYQ8X 3lsz5cDhAkEAwg+kDWbLtXWlIvXhhla7q0+RfKb8vu/gXnkXJa6rcJdJztKRbP3b 9fehVeu9m+1+abahjC1zmQimwd2QVc8BGQJADbtfCGaVPzpoho9TWQmaRO1mrYuf vZh7IiejEYvpHpWNn53cmrTDsTyvti7lG/APYzqYRxeW7M6UOS/+AaLAYQJAJbEW AwhZPphoB59MO2RzNPXSYyyn4IoEwTSxuz7uy4KG8mXRmyK/a0m6i06rWDLLn8q6 G9jkH/AfO35GP3RiWQJBAJLWBlKpHf8TxT65jAwxBhd9ZOkC2w0WidbSYjX9wkkD 38K7ZDm1LSIR69Ut6tdwotkytXvDniOMPY6ENar5IUs= -----END RSA PRIVATE KEY----- ``` The content of the sample ```insecure_device_cert.crt``` file is: ``` -----BEGIN CERTIFICATE----- MIIB8zCCAVwCAQEwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UEBhMCVVMxDzANBgNV BAgMBk9yZWdvbjERMA8GA1UEBwwIUG9ydGxhbmQxDzANBgNVBAoMBkdFTklWSTAe Fw0xNTExMjcyMzE0NTJaFw0xNjExMjYyMzE0NTJaMEIxCzAJBgNVBAYTAlVTMQ8w DQYDVQQIDAZPcmVnb24xETAPBgNVBAcMCFBvcnRsYW5kMQ8wDQYDVQQKDAZHRU5J VkkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJtviM8ARIrFquPc0myB9BuF 9MdkA/2SatqbZMWeTOUJHGrjBDEEMLQ7zk8AyBmi7RquYYZs67SyLhylVGKh6sJA lecxbHUwj7cZSS1bmKMje6L61gKwxBm2NIFU1cVl2jJlTaU9VYhM4xk57yj28nkN xSYWP1vbFX2NDX2iH7b5AgMBAAEwDQYJKoZIhvcNAQELBQADgYEAhbqVr9E/0M72 9nc6DI+qgqsRSMfoyvA3Cmn/ECxl1ybGkuzO7sB8fGjgMQ9zzcb6q1uP3wGjPioq MymiYYjUmCTvzdvRBZ+6SDjrZfwUuYexiKqI9AP6XKaHlAL14+rK+6HN4uIkZcIz PwSMHih1bsTRpyY5Z3CUDcDJkYtVbYs= -----END CERTIFICATE----- ``` These files are checked into ```priv/certificates``` and ```priv/keys```. **DO NOT USE THE KEYS AND CERTIFICATES ABOVE IN PRODUCTION!
ANY PRODUCTION KEYS SHOULD BE GENERATED BY THE ORGANIZATION AND BE 4096 BITS LONG.**
## RVI credentials format A credential is a JWT-encoded JSON structure, signed by the root X.509 certificate's private key, describing the rights that the sender has. A received RVI credential is validated as follows. 1. **Receive remote party's X.509 device certificate**
The TLS handshake process will exchange the X.509 certificates setup in the previous chapter. 2. **Validate remote party's X.509 device certificate**
The received device X.509 certificate has its signature validated by the root X.509 certificate that is pre-provisioned in all RVI nodes.
The receiver now knows that the remote RVI node has an identiy generated by a trusted provsioning server using the private root key. 3. **Receive one or more RVI credentials**
Each credential is encoded as JWT, signed by the root X.509 certificate. 4. **Validate each RVI credential signature**
The root X.509 certificate is used to validate the signature of each received RVI credential.
A successful validation proves that the certificate was generated by a trusted provisioning server using the private root key. 5. **Validate the credential-embedded X.509 device certificate**
Each received RVI credential will have its embedded device X.509 certificate compared with the device X.509 certificate received in step 1 above.
A match proves that the certificate was generated by a trusted provisioning server explictly for the RVI node at the remote end. An RVI credential has the following format in its native JSON state: ```JSON { "create_timestamp": 1439925416, "right_to_invoke": [ "jlr.com/vin/" ], "right_to_receive": [ "jlr.com/backend/sota" ], "id": "insecure_cert", "iss": "jaguarlandrover.com", "device_cert": "", "validity": { "start": 1420099200, "stop": 1925020799 } } ```
The members are as follows: Member | Description --------------------|--------------------- create\_timestamp | Unix timestamp of when the credential was created right\_to\_invoke | A list of service prefixes that the sender has the right to invoke on any node that has registered matching services that start with the given string(s). right\_to\_receive | A list of services that the sender has the right to to receive remote invocations for from remote nodes. id | A system-wide unique identifier for the credential. iss | The issuing organization. device_certificate | The PEM-encoded device X.509 certificate to match against the sender's TLS certificate. validity.start | The Unix timestamps when the credential becomes active. validity.stop | The Unix timestamps when the credential becomes inactive. ## Generating RVI credentials To create a credential, tie it to a device X.509 certificate, and sign it with a root X.509 certificate private key, the following command is used: ```Shell rvi_create_credential.py --cred_out="insecure_credential.json" \ --jwt_out='insecure_credential.jwt' \ --id="xxx" \ --issuer="genivi.org" \ --root_key=insecure_root_key.pem \ --device_cert=insecure_device_cert.crt \ --invoke='genivi.org/' \ --receive='genivi.org/' ``` The following command line parameters are accepted: Parameter | Required | Description -------------- | -------- | --------- --cred\_out | No | Output file containing the JSON-formatted un-encoded credential. --jwt\_out | Yes | JWT-encoded, JSON-formatted, root keyp-signed credential. --issuer | Yes | Organization that issued the credential. --root\_key | Yes | Private, PEM-encoded root key to sign the credential. Must be the same key used to sign the root X.509 certificate. --device\_cert | Yes | The PEM-encoded device X.509 certificate to embed into the credential as the device_cert member. --invoke | Yes | Space separated list (within quotes) of RVI service prefixes that the owner of the credential has the right to invoke. --receive | Yes | Space separated list (within quotes) of RVI service prefixes that the owner of the credential has the right to have invoked by other nodes (with the right credential). --start | No | The Unix timestamps when the credential becomes active. --stop | No | The Unix timestamps when the credential becomes inactive. The generated ```insecure_credential.json``` and ```insecure_credential.jwt``` are checked into ```priv/credentials```.