Page contents
Introduction
TeskaLabs SeaCat PKI documentation¶
Welcome to TeskaLabs SeaCat PKI documentation.
TeskaLabs SeaCat PKI¶
TeskaLabs SeaCat PKI is a cybersecurity software product for Public Key Infrastructure (PKI) management. This application is designed for creating and managing X.509 certificates, certificate requests (CSR), RSA and EC private keys and Certificate Revocation Lists (CRLs).
It provides everything that is needed for operating Certificate Authority (CA).
Made with ❤️ by TeskaLabs
TeskaLabs SeaCat PKI is a product of TeskaLabs.
Screenshots¶
Here are examples of the TeskaLabs SeaCat PKI web application.
Picture: Management of the available private keys.
Picture: Creating a new certificate request.
Technical specification¶
The TeskaLabs SeaCat PKI consists of a web application and a microservice. The microservice provides a REST API. The data are stored in a MongoDB database. The TeskaLabs SeaCat PKI can use various Hardware Security Modules(HSM) thru PKCS#11 interface. The user authentication is done via OAuth 2.0 with OpenID Connect protocol.
The TeskaLabs SeaCat PKI is designed to be operated as High-Availability system (aka geographically distributed cluster). Single node deployment is also possible.
The product is multi-tenant, which means that each tenant has its own data (certificates, keys, etc.) and can be operated independently.
The product can be deployed as on-premises or delivered as a service.
Features¶
- 
General
 - 
X.509
 - 
C-ITS Security (ETSI ITS-G5), C-V2X Security (LTE-V2X)
- ETSI TS 103 097 v1.3.1
 - ETSI TS 102 941 v1.3.1
 
 - 
User authentication and authorization
- OAuth 2.0
 - OpenID Connect protocol
 - Microsoft Active Directory integration
 - Role-Based Access Control
 
 
Note
TeskaLabs SeaCat PKI is built using Python, cryptography.io and OpenSSL
C-ITS Security¶
TeskaLabs SeaCat PKI provides a support for C-ITS (Cooperative Intelligent Transport Systems) security cryptographic system published by ETSI.
C-ITS Security is defined by following standards:
ETSI¶
- ETSI TS 102 941 v1.3.1, v1.2.1 - Security; Trust and Privacy Management [PDF]
 - ETSI TS 103 097 v1.3.1 - Certificate formats [PDF]
 - ASN.1 specifications
 
European Commission / JRC¶
- C-ITS Certificate Policy (EU CP)
 - C-ITS Security Policy (EU SP)
 
IEEE¶
- IEEE 1609.2-2016 - Security Services for Applications and Management Messages [paid]
 
Guides
Guides¶
This section contains guides for using TeskaLabs SeaCat PKI in various scenarios.
First Steps¶
As a first thing, you should Create a Certificate Authority to be able to issue certificates for your users and devices.
Create a Certificate Authority¶
A Certificate Authority (CA) is a trusted entity that issues digital certificates. To establish this trust, the CA itself must have a certificate. This certificate is typically self-signed, meaning the CA signs its own certificate. This self-signed certificate serves as the root of trust for all certificates issued by the CA. Without this self-signed certificate, the CA would not be able to validate the authenticity of the certificates it issues, and the entire chain of trust would be broken Therefore, creating a self-signed certificate for the CA is a crucial first step in setting up a Public Key Infrastructure (PKI).
Prerequisites¶
- TeskaLabs SeaCat PKI up and running in a default setup (SoftHSMv2 configured for an active tenant).
 - Access to a Web User Interface
 
Steps¶
- 
Navigate to the "Certificates" > "Create a certificate" screen
 - 
Fill in the form
- Select "Create a Self-Signed Certificate" option at "Source" tab
 - Select "Generate a new private key" option at "Private Key" dropdown
 - Type a label for the private key, i.e. "My CA Private Key"
 - Select "SoftHSM" at Private Key Provider dropdown, the private key will be generated in the HSM
 - Select "MySoftHSMToken" at PKCS#11 Token dropdown
 - Select "RSA" at Key Type dropdown
 - Select "4096" at Key Size dropdown
 - Select "Certificate Authority" at "Apply template" dropdown
 - Fill the label of the CA at "General" tab, i.e. "My CA"
 - Prolong the validity of the CA certificate at "Valid to", 10 years is a good default
 - Fill a Common Name for the CA at "Subject" tab, i.e. "My CA", feel free to add more fields to the subject
 - Click "Create" button to create a certificate
 
You can also modify other certificate attributes according your specific needs.
 - 
Review the created CA certificate
Congratulations! You have created a CA certificate.
You can download the CA certificate using a "Download" icon at the top right corner of the card.
Now you can create a certificate for a user or a device.
 
Approve a Certificate Signing Request¶
A Certificate Signing Request (CSR) is a request for a digital certificate from a Certificate Authority (CA). The CSR contains information about the requester's public key, the requested certificate's subject, and other relevant details. The CA uses this information to generate a certificate that can be used to verify the requester's identity and encrypt data.
Prerequisites¶
- TeskaLabs SeaCat PKI up and running in a default setup (SoftHSMv2 configured for an active tenant).
 - Access to a Web User Interface
 - A CSR created by a user
 - A CA certificate and a private key within the CA
 
Steps¶
- 
Navigate to the "Import" screen
Fill in the form:
- Type of imported material: "CSR"
 - Format: "PEM" or "DER" based on the actual format of the CSR file
 - File: upload the CSR file
 
 - 
Review the imported CSR
If the CSR contains a proper information, click on the "Approve" button. You can also delete a CSR to cancel the request.
 - 
Create a certificate
In this screen, fill in:
- The certificate authority in "Issuer" field.
 - Press "Copy Certificate Signing Request to Certificate" if you want to copy attributes from CSR
 - Review, change or add attributes on remain tabs
 - Press "Submit" to create a certitifate
 
 - 
Review the created certificate
Congratulations! You have created a certificate.
You can download the certificate using a "Download" icon at the top right corner of the card.
 
SCEP¶
SeaCat PKI supports SCEP aka Simple Certificate Enrolment Protocol.
Prerequisities¶
- Certificate Authority: (how to Create a Certificate Authority)
 
Enable SCEP¶
Use Web UI to enable SCEP in the Certificate Authority.
Press "Edit", select the checkbox and press "Save".
Resources¶
- Simple Certificate Enrolment Protocol (SCEP) Specifications, draft-gutmann-scep-16
 - RFC 2315 PKCS #7: Cryptographic Message Syntax
 - RFC 5652 Cryptographic Message Syntax (CMS)
 
Certificate Enrolment/Renewal¶
Certificate Enrolment procedure¶
Client C (aka sscep)
Certification Authority CA (aka SeaCat PKI)  
Cgenerates private/public key pairCgenerates CSR (aka Certificate Signing Request, PKCS#10)- Add attributes
 - Add a public key
 - Sign CSR by private key (Proof-of-Possession or PoP)
 Csubmits CSR toCAover SCEP (request is in the PKCS#7 aka CMS format)CAaccepts CSR (over SCEP interface, including PKCS# verifications)CAverifies CSRCAstores CSR into a storage- At this moment 
CAcan decide that the approval will be delayed and returnsPENDINGto theC. The process can be resumed here.Chas to periodically check the status of the enrollment withCA. CAapproves CSR and this step implicitly creates a client certificate- Add selected attributes from CSR
 - Add a public key from CSR
 - Sign a new certificate by its CA private key
 CAstores a new client certificate in a storageCretrieves this client certificate fromCA(over SCEP)Cstores the client certificate on the local drive
Note: Renewal process is similar to the enrolment.
Tool sscep¶
SSCEP is a command line client for the SCEP protocol.
It can be used as a client to SeaCat PKI.
- 
Configure SeaCat PKI SCEP entry point.
% export SCEP_URL="http://example.com/scep-tenant/scep" - 
Get CA Certificate
% sscep getca -c ca.cert -u ${SCEP_URL}Stores the CA certiticate into
ca.certfile. - 
Prepare CSR
% openssl req -newkey rsa:2048 -sha256 -nodes -out local.csr -keyout local.key -subj "/C=GB/L=London/O=TeskaLabs/OU=SeaCat/CN=example.com"This creates
local.keyandlocal.csr. - 
Certificate Enrolment
% sscep enroll -v -k local.key -r local.csr -c ca.cert -l local.cert -t 2 -u ${SCEP_URL} - 
Certificate Renewal
% sscep enroll -v -k local.key -r local.csr -c ca.cert -O local.cert -K local.key -l local.cert -u ${SCEP_URL} 
NGINX¶
This is how to configure NGINX to forward SCEP requests to SeaCat PKI (hostname my-seacat-pki, tenant mytenant).
location /my/scep {
        rewrite ^/my/scep /mytenant/scep break;
        proxy_pass http://my-seacat-pki:8910;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Apple SCEP support¶
Apple allows to specify a profile for macOS and iOS that contains SCEP specifications allowing automated device enrollment.
Documentation:
- Configuration Profile Reference (Apple, PDF)
 - Configuration Profiles (Online, Substitution Variables for profiles)
 
SCEP profile¶
- 
Download the ./scep-apple-profile.mobileconfig file. The profile is XML file. Ensure that the file has
.mobileconfigextension. - 
Use the text editor to customize the profile accordingly to your setup, namely provide the URL of your SeaCat PKI SCEP endpoint.
 - 
Open this file in a Finder to invoke "Profile installation"
 - 
Go to "System Settings" > "Profile" and double-click the new SCEP profile to finish the installation. The certificate must be approved by SeaCat PKI during this step, so consider using auto-approve function of the PKI.
 
TR-069¶
How to implement TR-069, ACS & Mutual TLS Authentication using TeskaLabs SeaCat PKI.
This document elaborates on how to implement secure, mutually authenticated TLS communication between CPE and ACS for TR-069. The base of this technical specification is the Technical Report "TR-069 CPE WAN Management Protocol Issue: 1 Amendment 6" published by The Broadband Forum.
It details how to enrol CPE using SCEP.
Architecture¶
Remarks¶
- TR-069 client on CPE is an HTTPS client
 - ACS is an HTTP server
 - NGINX provides HTTPS termination and mutual TLS authentication
 - SeaCat PKI provides CA capability (Certification Authority)
 - SCEP client on CPE uses HTTP/1.0 protocol which is prescribed by SCEP specification
 
Certificates¶
Server CA Certificate¶
A long-term (20+ years) X.509 certificate that is pre-loaded into CPE during manufacturing. Also named "trusted root certificate".
CPE CA Certificate¶
A long-term (20+ years) X.509 certificate that downloaded into CPE using SCEP tool. CPE Certification Authority (CA) is operated by SeaCat PKI. This is typically different certificate from Server CA certificate.
CPE Certificate¶
A shorter (~ 1 year) unique CPE client certificate that is generated (enrollment) and renewed during a CPE lifecycle using SCEP. It is generated by SeaCat PKI CA, using CPE CA Certificate, based on the SCEP request from CPE (enrollment or renewal). The CPE private key is generated and stored on the CPE. Also named "client certificate".
Server Certificate¶
Issued by Server CA for 3 months, renewed periodically.
Detailed CPE ceremonies for Unique CPE client certificate¶
The ceremonies are handled by SCEP.
Enrollment¶
This is initial ceremony that obtains a first client certificate for CPE.
Triggered: After the CPE network connectivity becomes available, can be triggered periodically.
Pre-condition: CPE doesn't have the client certificate.
- CPE generates a client private/public key pair (CPK)
 - CPE generates a Certificate Signing Request (CSR) using CPK
 - CPE submits CSR to a SeaCat PKI over HTTPS PUT call (no client certificate is needed).
 - The response contains a Client certificate or an error code.
 - If error, the enrollment ceremony is restarted after 1 minute.
 - The Client certificate is stored on CPE permanent storage and used with CPK for TR-069 / HTTPS calls to ACS.
 
CSR details:
- The value of the CN field of CSR (and client certificate) MUST be globally unique for each CPE. Specifically, the CN field MUST adhere to the format recommended for the username/userid in TR-069 CPE WAN Management Protocol Issue: 1 Amendment 6 Section 3.4.4.
 
Renewal¶
This is regular ceremony that renews a client certificate when it's lifecycle is ending.
Triggered: After the CPE network connectivity becomes available and periodically 4x per day.
Pre-condition: CPE has the client certificate (even expired).
- CPE checks if the client certificate is about to expire or expired
 - If a client certificate is expiring, CPE generates a new CSR
 - CPE submits CSR to a SeaCat PKI over HTTPS PUT call (no client certificate is needed).
 - The response contains a Client certificate or an error code.
 - If error, this ceremony is restarted after 1 minute, when a client certificate is expired or after 4 hours when not yet expired.
 - The Client certificate is stored on CPE permanent storage and used with CPK for TR-069 / HTTPS calls to ACS.
 
Remark: CRS requirements are the same as for Enrollment.
Remark: The renewal ceremony is very similar to an enrollment.
Communication flow¶
HTTPS/TLS specification¶
- TLS v1.2+
 - RSA 2048 for CPE
 - RSA 4096 for Server
 - RSA 8192 for CA
 TLS_RSA_WITH_AES_128_CBC_SHA
Reference¶
- 
RFC 2986
PKCS #10: Certification Request Syntax Specification
CSR, PKCS#10 - 
TR-069 / CPE WAN Management Protocol
Issue: 1 Amendment 6
The Broadband Forum - 
SCEP: Simple Certificate Enrolment Protocol
Internet Draft
Network Working Group, Internet Engineering Task Force (IETF) 
SeaCat Mutual TLS¶
PKI for mobile applications and IoT.
This is a SeaCat extension to X.509 certificate crypto family.
PKI Initialization¶
$ openssl ecparam -name prime256v1 -genkey -noout -out seacat_private_key.pem
[tenants]
ids=TENANT
[seacatpki:private_key:TENANT_seacat_private_key]
tenants=TENANT
keyfile=./TENANT/seacat_private_key.pem
[seacatpki:x509:ca:TENANT]
ca_key=TENANT_seacat_private_key
Note: Assuming that "TENANT" is a name of the tenant.
Client Certificate Authority¶
curl -X PUT \
  'http://localhost:8080/TENANT/x509/self-signed' \
  -H 'Content-Type: application/json' \
  -d '{
        "serialNumber": 1,
        "subject": {
            "O": "My Org", "CN": "Root CA"
        },
        "validity": {
            "notBefore": "now",
            "notAfter": { "weeks": 1040 }
        },
        "extensions": [
            { "basicConstraints": {
                "CA": true,
                "pathLen": 0
            }, "critical": true } ,
            { "keyUsage": [
                "keyCertSign",
                "cRLSign"
            ] }
        ]
    }'
[tenants]
ids=TENANT
[seacatpki:private_key:TENANT_seacat_private_key]
tenants=TENANT
keyfile=./TENANT/seacat_private_key.pem
[seacatpki:x509:ca:TENANT]
ca_key=TENANT_seacat_private_key
ca_cert=TENANT:18222c51d1c5e96f9a3ceb5b2b739943ce7c0b5e2dcb639c7fd0c1cab06a088f74dfd9988bade47bb18273d039753ef8
seacat=yes
SeaCat TLS specifications¶
Mutual TLS/SSL authentication
Client Certification Authority¶
CA is used to enroll SeaCat clients and in the process of a client verification during TLS handshake.
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: O=TeskaLabs, OU=SeaCat, CN=Devel Root CA
        Validity
            Not Before: Sep 22 00:00:00 2019 GMT
            Not After : Sep 21 23:59:59 2039 GMT
        Subject: O=TeskaLabs, OU=SeaCat, CN=Devel Root CA
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:db:16:df:53:73:9a:b4:22:aa:e9:21:22:0c:de:
                    84:c4:2f:23:1e:eb:86:37:1f:54:7b:6d:b6:47:04:
                    37:e2:fb:b2:34:e1:0f:a2:95:0e:c8:c7:ab:fc:78:
                    fc:ae:9f:78:72:e7:03:d2:19:2f:dd:4c:1e:e3:57:
                    a9:f1:ae:a5:c0
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 Subject Key Identifier:
                75:BD:5E:00:9E:C3:F5:1D:8E:7B:AD:33:C5:C9:0C:E9:79:B8:A7:22
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:20:1c:6e:54:ba:70:a5:46:e0:a4:b0:d3:70:90:ce:
         35:f6:2d:ec:e4:2e:c6:96:91:47:00:1b:d7:30:d7:b8:92:dc:
         02:21:00:c2:88:0c:ac:51:c4:bd:66:44:85:c8:53:84:8e:b3:
         0f:db:37:27:63:ab:d1:7c:dd:5a:1a:c1:02:9a:11:a4:1c
Highlights:
- Self-signed (root) certificate
 - EC Nist P-256 / prime256v1
 - CA:TRUE, pathlen:0
 - Key Usage: Certificate Sign, CRL Sign
 
Gateway¶
- EC Key NIST P-256 aka secp256r1 and prime256r1 (P-384 is supported by iOS and Android > 7)
 - Ciphers: ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-ECDSA-CHACHA20-POLY1305
 - Session ID enabled
 - Session Tickets disabled
 - Send client CA certificate (from SeaCat PKI)
 - Verify depth: 1
 
Example configuration from a OpenSSL:
openssl s_server -www -accept "*:443" \
    -key seacat_gw.key \
    -cert seacat_gw.cert \
    -Verify 1 \
    -CAfile seacat_client_ca.pem
Note: Only a client verification is covered in this example.
NGINX as a Gateway¶
proxy_cache_path seacat_auth.cache keys_zone=seacat_auth:40m max_size=100m;
server {
    listen       80 default_server;
    server_name  _;
    server_tokens off;
    access_log /log/nginx-access.log;
    error_log /log/nginx-error.log;
    # We use acme.sh for a gateway certificate
    location /.well-known/acme-challenge/ {
        default_type          text/plain;
        proxy_read_timeout    60;
        proxy_connect_timeout 60;
        proxy_redirect        off;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header      X-Forwarded-Proto $scheme;
        proxy_set_header      Host $host;
        proxy_pass            http://acme-sh;
    }
    location / {
        return 301 https://teskalabs.com;
    }
}
server {
    listen 443 default_server ssl http2;
    server_name  _;
    server_tokens off;
    access_log /log/nginx-access-ssl.log;
    error_log /log/nginx-error-ssl.log;
    ssl_certificate /acme.sh/example.com_ecc/fullchain.cer;
    ssl_certificate_key /acme.sh/example.com_ecc/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:DH+AES256:ECDH+AES128:!aNULL:!MD5:!DSS:!AESCCM;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 4h;
    add_header Strict-Transport-Security max-age=31536000;
    # Verify client certificates
    ssl_verify_client optional;
    ssl_client_certificate conf.d/seacat_ca.pem;
    # SeaCat PKI public api
    location /seacat {
        proxy_redirect        off;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header      X-Forwarded-Proto $scheme;
        proxy_set_header      Host $host;
        proxy_pass            http://seacatpki:8080/seacat/seacat;
    }
    # The location that is restricted only to authenticated clients
    location /restricted {
        # Authenticate using SeaCat PKI
        auth_request /_seacat_pki_auth;
        # Set X-SeaCat-Identity header based on the value received from a SeaCat PKI authentication call
        auth_request_set $seacat_identity $upstream_http_x_seacat_identity;
        proxy_set_header X-SeaCat-Identity $seacat_identity;
        #proxy_pass https://restricted.example.com;
        #proxy_ssl_server_name on;
    }
    # This is an internal authentication call to SeaCat PKI to validate the client identity
    location = /_seacat_pki_auth {
        internal;
        proxy_method          PUT;
        proxy_set_header      X-SSL-Client-Verify $ssl_client_verify;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header      X-Forwarded-Host $host;
        proxy_set_header      X-Forwarded-Request $request;
        proxy_set_body        "$ssl_client_raw_cert";
        proxy_pass            http://seacatpki:8080/seacat-tenant/seacat/nginx_authenticate;
        # Responses are cached to reduce a load on SeaCat PKI
        proxy_cache           seacat_auth;
        proxy_cache_key       $ssl_client_fingerprint;
        proxy_cache_lock      on;
        proxy_cache_valid     200 360s;
        proxy_ignore_headers  Cache-Control Expires Set-Cookie;
    }
    location / {
        return 301 https://teskalabs.com;
    }
}
Note: For more details, see a docker chapter.
Let's Encrypt for a Gateway certificate¶
The gateway certificate (or server certificate) can be issued by e.g. Let's Encrypt.
acme.sh client has to be used because EC keypair is needed (not RSA).
Example from a Docker Compose:
docker-compose exec acme-sh acme.sh --standalone --keylength ec-256 --issue -d CHANGEME.seacat.io
Note: certbot client has limited support for ECC (basically, automated renewal is very tricky).
It is possible to use certbot but we strongly don't recommend that.
Client¶
TODO: Any kind of server certificate pinning?
Enrolment Validation¶
This is a client REST call that SeaCat PKI can perform to an external service to validate if CR can be approved and therefore SeaCat identity granted to a client.
The URL configuration goes to approve config item"
[seacat:seacat]
ca_cert=...
ca_key=...
approve=http://example.com/validate_cr
SeaCat PKI does a POST call with a following body:
{
    '_c': '2019-12-13T13:31:11.158000',
    '_id': '...',
    '_m': '2019-12-13T13:31:11.158000',
    '_v': 1,
    'data': '3081f2a0819a800219028119636f6d2e7465736b616c6162732e7365616361742e64656d6f820d3139313231333134333131305a830d3139313231333134333631305aa459a01380072a8648ce3d020181082a8648ce3d03010781420004161ed21a40c02116ff718edd3333e68ef1976627d790548a084fd9dcaee8cb95df5b49a81d403a3ef7a3ba41c662d731fc5ca8523333b02a542411d5953a4ef2a500a10a80082a8648ce3d0403028247304502210086b3c27afb163412a655b89f62a3a969a1d7732857e2598240ae8e61e614b76a022042e159e02c8b5cd7892587f4ad76caf68796197bc58d4204c3dd3c90f6926c4d',
    'family': 'seacat',
    'info': {
        'application': 'com.teskalabs.seacat.demo',
        'identity': 'HDKXPDREZADFK4G2'
    },
    'label': 'HDKXPDREZADFK4G2 (com.teskalabs.seacat.demo)',
    'seacat_application': 'com.teskalabs.seacat.demo',
    'seacat_identity': 'HDKXPDREZADFK4G2',
    'tenant': 'seacat',
    'type': 'cr'
}
Note: It is the equivalent information to "Get the cryptomaterial meta" REST call of SeaCat PKI.
The expected response HAS TO BE JSON. The CR will be approved only if the content is a following structure:
{ "result": "OK" }
Administration
Cluster¶
TeskaLabs SeaCat PKI can be deployed as a single instance or as a cluster. The cluster can be geographically distributed to provide high availability and disaster recovery.
Cluster Architecture¶
The architecture diagram illustrates the deployment options of TeskaLabs SeaCat PKI in containers, highlighting the components involved in both single-instance and clustered configurations:
- 
Single Instance (Left side of the diagram):
- Components:
- NGINX: Acts as a reverse proxy to handle incoming requests and route them to the appropriate services.
 - Web UI: Provides an interface for managing the PKI.
 - SeaCat PKI: The core PKI microservice that issues and manages certificates.
 - HSM (Hardware Security Module): Optional integration for secure key storage.
 - MongoDB: Serves as the database backend for storing certificate data and configurations.
 
 - All components are containerized within a single Docker/Podman instance, providing simplicity in deployment and maintenance.
 
 - Components:
 - 
Clustered Configuration (Right side of the diagram):
- Cluster Characteristics:
- Components are identical to the single-instance setup but are distributed across multiple nodes.
 - Multiple instances of SeaCat PKI and MongoDB ensure redundancy and high availability.
 
 - Geographical Distribution:
- Nodes in the cluster can be deployed in different geographical locations, enabling disaster recovery and improving fault tolerance.
 
 - Synchronization:
- The MongoDB instances synchronize across the cluster to maintain data consistency.
 - The content of HSM must be synchronized across the cluster using HSM management tools.
 
 
 - Cluster Characteristics:
 
Both configurations allow flexible deployment to meet different scalability, reliability, and performance requirements.
Containerization¶
TeskaLabs SeaCat PKI is a Docker and Podman friendly.
The backend microservice can be deployed as a container, together with the rest of the application ecosystem (NGINX, MongoDB, etc.).
The whole containerized deployment can be orchestrated by docker compose, Kubernetes and other container orchestration tools.
Deployment via docker-compose¶
Used containers:
mongo: MongoDB databasenginx: NGINX API Gatewayseacatpki: TeskaLabs SeaCat PKI microserviceacme.sh: acme.sh Let's Encrypt client (optional)
Directory structure¶
docker-compose.yamlconf-nginx/nginx.conf
conf-seacatpki/seacatpki.conf
seacatpki/# SeaCat PKI Git repository clonedata-mongo/# A persistent data folder for Mongo DBlog/# Log filesacme.sh/# Let's encrypt / acme.sh files
docker-compose.yaml¶
services:
    mongo:
        image: mongo
        volumes:
        - ./data-mongo:/data/db
        - ./log:/log
        networks:
        - seacatpkinet
    nginx:
        image: nginx:latest
        depends_on:
        - seacatpki
        ports:
        - 80:80/tcp
        - 443:443/tcp
        volumes:
        - ./conf-nginx:/etc/nginx/conf.d
        - ./log:/log
        - ./acme.sh:/acme.sh
        networks:
        - seacatpkinet
    seacatpki:
        build: .
        depends_on:
        - mongo
        volumes:
        - ./conf-seacatpki:/conf
        - ./log:/log
        networks:
        - seacatpkinet
    acme-sh:
        image: neilpang/acme.sh
        command: daemon
        volumes:
        - ./acme.sh:/acme.sh
        networks:
        - seacatpkinet
networks:
    seacatpkinet:
        driver: bridge
nginx.conf¶
server {
    listen 80 default_server;
    server_name  _;
    server_tokens off;
    access_log /log/nginx-access.log;
    error_log /log/nginx-error.log;
    location /.well-known/acme-challenge/ {
        default_type          text/plain;
        proxy_read_timeout    60;
        proxy_connect_timeout 60;
        proxy_redirect        off;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header      X-Forwarded-Proto $scheme;
        proxy_set_header      Host $host;
        proxy_pass            http://acme-sh;
    }
}
server {
    listen 443 default_server ssl http2;
    server_name  _;
    server_tokens off;
    access_log /log/nginx-access-ssl.log;
    error_log /log/nginx-error-ssl.log;
    ssl_certificate /acme.sh/example.com_ecc/fullchain.cer;
    ssl_certificate_key /acme.sh/example.com_ecc/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 4h;
    add_header Strict-Transport-Security max-age=31536000;
    location / {
        return 301 https://example.com;
    }
}
Note
The SSL part (443) may be added only after acme.sh (below) issues certificate.
seacatpki.conf¶
[asab:storage]
type=mongodb
mongodb_uri=mongodb://mongo:27017/
mongodb_database=seacatpkidb
[web]
listen=0.0.0.0 8080
[logging:file]
path=/log/seacatpki.log
acme.sh¶
The script acme.sh is used to obtain Let's Encrypt certificate.
$ docker-compose exec acme-sh acme.sh \
    --update-account --accountemail you@yourdomain.com
$ docker-compose exec acme-sh acme.sh \
    --standalone --keylength ec-384 --issue -d example.com
Tip
Automatic renewals are handled by this container too.
Container image¶
The TeskaLabs SeaCat PKI microservice image is based on Alpine Linux. TeskaLabs distributes the container image via its private container registry.
The container image contains SoftHSM2 and OpenSSL libraries.
Dockerfile
There is a Dockerfile available in the root of the SeaCat PKI microservice repository.
Deploying into LXD container¶
Container setup¶
1) Launch a new LXC container based on Alpine.
$ lxc launch images:alpine/3.21 seacat-pki
$ lxc exec seacat-pki /bin/ash
2) Install the required packages.
In the newly launched LXC container:
$ apk update
$ apk upgrade
$ apk add --no-cache \
  python3 \
  py3-pip \
  libstdc++ \
  openssl
$ apk add --no-cache --virtual buildenv \
  openssh-client \
  git \
  python3-dev \
  libffi-dev \
  openssl-dev \
  gcc \
  g++ \
  swig \
  musl-dev
$ pip3 install --upgrade pip
$ pip3 install --no-cache-dir aiohttp
$ pip3 install --no-cache-dir asn1tools
$ pip3 install --no-cache-dir motor
$ pip3 install --no-cache-dir cryptography
$ pip3 install --no-cache-dir fastjsonschema
$ pip3 install --no-cache-dir asn1crypto
$ pip3 install --no-cache-dir PyKCS11
$ pip3 install --no-cache-dir git+https://github.com/TeskaLabs/asab.git
$ apk del buildenv
$ cd /opt
$ ... deploy the SeaCat PKI repository into /opt/seacat-pki ...
$ mkdir /opt/site-xxx
$ vi /opt/site-xxx/seacatpki.conf
3) Create the init.d (autostart) script.
Filename: /etc/init.d/seacatpki
#!/sbin/openrc-run
name="seacatpki"
command="/usr/bin/python3 /opt/seacat-pki/seacat-pki.py -c /opt/site-xxx/seacatpki.conf"
pidfile="/var/run/$SVCNAME.pid"
command_background="yes"
depend() {
    need net
    use dns
}
3) Start the service.
$ rc-service seacatpki start
X.509
Reference
HSM
Hardware Security Modules (HSM)¶
TeskaLabs SeaCat PKI supports hardware security modules (HSM) with PKCS#11 interface.
Specifically, HSMs are used for private key generation and management and also for random number generation.
Warning
TeskaLabs SeaCat PKI currently supports only one configured PKCS#11 module, you cannot configure multiple modules in the one PKI instance. You can use multiple tokens of the same module.
Configuration¶
seacatpki.conf:
[seacatpki:pkcs11:<identification>]
path=/path/to/pkcs11module.so
identificationis the internal name of the PKCS#11 provider (e.g.softhsm2)- 
pathis the location of the PKCS#11 module in the file system - 
session_persistenceis a boolean flag that indicates whether the PKCS#11 session should be kept open after use (default istrue). Some tokens closes the session after use, so this flag should be set tofalsefor such tokens. Setting this flag tofalsewill impact the performance of the HSM. 
Autoscan configuration¶
This approach means that the PKI will automatically scan the PKCS#11 tokens for available private keys.
seacatpki.conf:
[seacatpki:pkcs11:<identification>]
path=/path/to/pkcs11module.so
tokens=
    SoftHSMToken1,PIN1,tenant1
    SoftHSMToken2,PIN2,tenant2
    SoftHSMToken3,PIN2,tenant3
    ...
tokensis the list of tokens in the HSM
Each token is defined by:
token_nameis the name of the token (e.g.SoftHSMToken1)pinis the PIN of the token (e.g.PIN1)tenantis the name of the tenant that has access to the token (e.g.tenant1)
Explicit configuration¶
This approach means that the PKI will use only the private keys that are explicitly configured in the seacatpki.conf file.
[seacatpki:pkcs11:<identification>]
path=/path/to/pkcs11module.so
[seacatpki:private_key:<keyname>]
provider=pkcs11:<identification>
tenants=tenant1,tenant2
token_label=SoftHSMToken1
pin=PIN
cka_id=100002
keynameis the internal name of the private key (e.g.my_rsa_key)provideris the internal name of the PKCS#11 module (e.g.softhsm2)tenantsis the list of tenants that has access to the token (e.g.tenant1,tenant2)token_labelis the label of the token (e.g.SoftHSMToken1)pinis the PIN of the token (e.g.PIN)cka_idis the ID of the private key (e.g.100002)
Private key requirements¶
Private keys located at PKCS#11 tokens must have the following requirements:
CKA_CLASSmust beCKO_PRIVATE_KEYCKA_LABELmust be setCKA_IDmust be set and unique for each private key- There must be an exportable public key (
CKA_CLASSmust beCKO_PUBLIC_KEY) with the sameCKA_ID 
SoftHSMv2¶
SoftHSM is a software cryptographic store accessible through a PKCS#11 interface. It is an emulator of a Hardware Security Module (HSM) that runs on the main CPU.
TeskaLabs SeaCat PKI supports SoftHSMv2.
More at: http://www.softhsm.org
Tip
SoftHSMv2 is available in the TeskaLabs SeaCat PKI Container image.
SoftHSM2 preparation¶
1) Prepare a SoftHSM2 configuration file
softhsm2.conf:
directories.tokendir = ...softhsm/tokens/
objectstore.backend = file
log.level = INFO
Note
directories.tokendir is a location of where SoftHSM2 stores private keys and other objects.
2) Specify the location of the SoftHSM2 configuration file
export SOFTHSM2_CONF=.../softhsm2.conf
Note
SOFTHSM2_CONF environment variable must be set also for TeskaLabs SeaCat PKI microservice runtime.
3) Initialize token
% softhsm2-util --init-token --free --label "MySoftHSMToken"
Slot 0 has a free/uninitialized token.
=== SO PIN (4-255 characters) ===
Please enter SO PIN: ********
Please reenter SO PIN: ********
=== User PIN (4-255 characters) ===
Please enter user PIN: ******
Please reenter user PIN: ******
The token has been initialized and is reassigned to slot 1735718982
--free means that the first free/uninitialized token in SoftHSM2 instance will be used.
The User PIN is used in the configuration of the token in secatpki.conf.
Danger
label has to be a unique token label in the SoftHSM2 instance.
Running softhsm2-util in the Docker container
$ docker exec -it 
4) Add a SoftHSM2 modeule in SeaCat PKI configuration
secatpki.conf:
[seacatpki:pkcs11:softhsm2]
path=.../libsofthsm2.so
tokens=
    MySoftHSMToken,<pin>,mytenant
The token "MySoftHSMToken" will be made available to the tenant "mytenant".
Tip
softhsm2 is an internal name of provider and can be chosen freely.
4) Restart SeaCat PKI microservice
Generation of the private key¶
Private keys can be generated from SeaCat PKI web interface or using pkcs11-tool command line tool.
The later approach is described here.
Generate EC private key¶
pkcs11-tool --module .../libsofthsm2.so --login --token-label "MySoftHSMToken" --keypairgen --label "ECKey" --id 100001 --key-type EC:brainpoolP384r1
Generate RSA private key¶
pkcs11-tool --module .../libsofthsm2.so --login --token-label "MySoftHSMToken" --keypairgen --label "RSAKey" --id 100002 --key-type RSA:2048
Danger
--id is a unique identifier of the private key in the token and must be provided.
Add a SoftHSM2 private key explicitly¶
You may want to add a private key explicitly into SeaCat PKI configuration.
secatpki.conf:
[seacatpki:private_key:softhsm2_key]
provider=pkcs11:softhsm2
tenants=tenant1,tenant2
token_label=MySoftHSMToken
pin=<PIN>
cka_id=100001
Random Number Generator¶
SoftHSM2 can be used as random number generator (RNG) in TeskaLabs SeaCat PKI. It is not practical but possible.
Initialize a dedicated token for RNG:
$ softhsm2-util --init-token --free --label "MyRandomNumberGenerator"
secatpki.conf:
[seacatpki:random]
provider=pkcs11:softhsm2
pin=<PIN>
token_label=MyRandomNumberGenerator
Troubleshooting¶
RuntimeError: Initialisation error (not initialized). Should never see this.
You need to set SOFTHSM2_CONF environment variable properly.
YubiHSM 2¶
The YubiHSM 2 is a small Hardware Security Module (HSM) that fits into USB port.
YubiHSM 2 preparation¶
1) Prepare a YubiHSM2 configuration file
The configuration file yubihsm2_pkcs11.conf must be located in the working directory of TeskaLabs SeaCat PKI microservice.
.../yubihsm2_pkcs11.conf:
connector = http://yubihsm:12345
yubihsm is a host that runs YubiHSM2 software.
YubiHSM 2 works in a way that the host with USB runs YubiHSM2 server that provides HTTPS API on a port 12345.
2) Configure SeaCat PKI to use YubiHSM 2 token
seacatpki.conf:
[seacatpki:pkcs11:yubihsm2]
path=.../yubihsm_pkcs11.dylib
tokens=YubiHSM,0001password,mytenant
pathis the location of the YubiHSM2 PKCS11 library (yubihsm_pkcs11.dyliboryubihsm_pkcs11.so).tokensis the configuration of the YubiHSM2 instance:- YubiHSM is a token name
 0001passwordis a PIN (change it to your own, first four digits reffers to a domain on YubiHSM)mytenantis a tenant that has an to the YubiHSM 2 token
Warning
YubiHSM2 offers a single token named "YubiHSM".
3) Restart SeaCat PKI microservice
Multi-tenancy¶
YubiHSM provides Domains as a means of logical secure storage partitioning. Each domain can be linked with authentication key(s) on the YubiKey, which can be represented by the password. The maximum number of domains on the YubiHSM is 16.
Example of a seacatpki.conf:
[seacatpki:pkcs11:yubihsm2]
session_persistence=false
path=.../yubihsm_pkcs11.dylib
tokens=
    YubiHSM,0001password1,tenant1
    YubiHSM,0002password2,tenant2
    YubiHSM,0003password3,tenant3
The authentication key identifier is captured in the hexadecimal (0000) part (fixed 4 digits) of the PKCS#11 PIN and then mapped to the respective tenant.
Example from yubihsm-shell:
connect
session open 1 password
put authkey 1 2 authkey1 1 all all password1
put authkey 1 3 authkey2 2 all all password2
put authkey 1 4 authkey3 3 all all password3
put authkey 1 2 tenant1 1 all all password1
put authkeyis a command to insert the authentication key into a YubiHSM1is a session number, modify that based on the session number fromsession open ...command2(etc) is a slot number into which the authentication key will be placedauthkey1(etc) is the name of the authentication key1(etc) is a domain numberallis requesting all YubiHSM2 capabilities; adjust this for lower permissionsallis requesting all YubiHSM2 delegated capabilities; adjust this for lower permissionspassword1(etc) is the seed for the authentication key, also this is used in PKCS#11 PIN.
Danger
Always use strong passwords when working with YubiHSM2.
Replace `password` in these examples by strong password in your deployment.
The PKCS#11 session persistence (session_persistence) must be disabled since only one session can be in progress when working with YubiHSM over PKCS#11.
Random Number Generator¶
YubiHSM 2 can be used as random number generator (RNG) in TeskaLabs SeaCat PKI.
secatpki.conf:
[seacatpki:random]
provider=pkcs11:yubihsm2
token_label=YubiHSM
YubiKey¶
YubiKey token can be also used as a "poor man's" hardware security module (HSM) in TeskaLabs SeaCat PKI.
secatpki.conf:
[seacatpki:pkcs11:yubikey]
path=/usr/local/lib/libykcs11.dylib
tokens=
    YubiKey PIV #xxxxxx,<PIN>,mytenant
session_persistence=false
Danger
session_persistence must be set to false for YubiKey token.
Utimaco CryptoServer CP5¶
TeskaLabs SeaCat PKI supports family of Utimaco CryptoServer CP5 HSMs.
Configuration¶
[seacatpki:pkcs11:utimaco]
path=.../Software/Linux/x86-64/Crypto_APIs/PKCS11_R2/lib/libcs_pkcs11_R2.so
[seacatpki:private_key:test-key]
provider=pkcs11:utimaco
tenants=test_ca
token_serial=53653132202020202020202020202038
token_label=TEST_TOKEN
pin=123456
cka_id=100102
p11-kit¶
p11-kit is a proxy PKCS#11 module. This p11-kit proxy module acts like a normal PKCS#11 module, but internally loads a preconfigured set of PKCS#11 modules and manages their features as described earlier Each slot in the configured modules is exposed as a slot of the p11-kit proxy module.
It basically allow to combine multiple PKCS#11 modules (i.e. HSMs) to be used at once.
TeskaLabs SeaCat PKI supports p11-kit.
More at: p11-glue.github.io (Manual), specifically "Proxy Module".
p11-kit configuration¶
Each module is configured by a dedicated configration file in the pkcs11/modules/ directory.
Simple example:
/opt/local/etc/pkcs11/modules/softhsm2:
module: /opt/local/lib/softhsm/libsofthsm2.so
The configuration simply contains a path of the underlaying PKCS#11 module, in this case it is SoftHSM2.
Random Number Generators¶
TeskaLabs SeaCat PKI uses software random number generators (RNG) by default, specifically Python secrets module, respectively OpenSSL RNG functions.
TeskaLabs SeaCat PKI also supports hardware random number generators (RNG) via PKCS#11.
Warning
Hardware RNGs are used only for certain cryptographic operations, e.g. key generation. Software keys (if used) are generated using software RNG.
Configuration of the PKCS#11 RNG provider¶
Snipplet from seacatpki.conf:
[seacatpki:pkcs11:myhsm]
path=/usr/lib/softhsm/myhsm.dylib
[seacatpki:random]
provider=pkcs11:myhsm
token_label=RNGToken
pin=<PIN>
provideris the identification of the provider, prefixed withpkcs11:means that the provider is a PKCS#11 tokentoken_labelis the label of the token within the providerpinis the PIN of the token (optional, if the token is already configured)
Tip
Dedicated PKCS#11 token for Random Number Generator is recommended.
C-ITS Security
Setup of C-ITS Security PKI¶
Note
Technical standards: ETSI TS 102 941 v1.3.1, v1.2.1 & ETSI TS 103 097 v1.3.1
Tip
The templates for certificates, certificate requests, CTL and CRL are in the templates folder.
Generate the Root CA certificate¶
Prerequisite: SeaCat PKI is installed, configured and stopped.
- 
Introduce a new tenant
Add
TENANT_ROOT_CAinto tenants, pick the descriptive lower-case ASCII only name inetc/seacatpki.conf:[tenants] ids=TENANT_ROOT_CA - 
Specify a SeaCat PKI API base URL
export ROOT_CA_URL=http://localhost:8080/TENANT_ROOT_CA - 
Generate the Root CA private/public key pair
Select one of the following EC curves:
Brainpool P-386 (
brainpoolP384r1)openssl ecparam -name brainpoolP384r1 -genkey -noout -out root-ca-private-key.pemPKCS#11 variant:
pkcs11-tool --module ... --login --keypairgen --id 10001 --key-type EC:brainpoolP384r1Brainpool P-256 (
brainpoolP256r1)openssl ecparam -name brainpoolP256r1 -genkey -noout -out root-ca-private-key.pemNIST P-256 (
prime256v1,secp256r1)openssl ecparam -name prime256v1 -genkey -noout -out root-ca-private-key.pemNote: You can share the same private key among various versions of C-ITS or even X.509.
 - 
Add a new private key into the configuration file
in
etc/seacatpki.conf:[seacatpki:private_key:TENANT_ROOT_CA_KEY_NAME] keyfile=${THIS_DIR}/root-ca-private-key.pem tenants=TENANT_ROOT_CA - 
Start SeaCat PKI
 - 
Create self-signed Root CA certificate
Use the template rootca.json and adjust if needed.
curl -X PUT "${ROOT_CA_URL}/cits/rca/self-signed?ca_private_key=TENANT_ROOT_CA_KEY_NAME" \ --header 'Content-Type: application/json' \ -d @templates/rootca.jsonNote the value of
pbidattribute from the response, it is a public object ID of a new certificate. - 
Introduce a new tenant for a trust domain
Note: Trust domain steps could be skipped, if trust domain exists
Add
TENANT_TRUST_DOMAINinto tenants, pick the descriptive lower-case ASCII only name inetc/seacatpki.conf:[tenants] ids=TENANT_ROOT_CA TENANT_TRUST_DOMAIN - 
Setup a trust domain
in
etc/seacatpki.conf:EU ECTL TLM L0 trust domain:
[seacatpki:cits:trust:TENANT_TRUST_DOMAIN] tlm_certificate=https://cpoc.jrc.ec.europa.eu/L0/gettlmcertificate/Example of the empty trust domain:
[seacatpki:cits:trust:TENANT_TRUST_DOMAIN] ; This is empty trust domain - 
Configure a new Root CA in SeaCat PKI configuration file
in
etc/seacatpki.conf:[seacatpki:cits:ca:TENANT_ROOT_CA] certificate=<pbid> trust_domain=<TENANT_TRUST_DOMAIN> # Optional crl_sign=digest/certificate crl_validity_days=<number-of-days>- Specify the 
pbidof the newly generated Root CA Certificate from a step above. - Specify 
crl_signif desired. Default (even if not specified) is digest only in the CRL. - If needed, default 
crl_validity_dayscan be configured, it specifies the number of days the CRL should be valid. If supplied, parameter "nextUpdate" in request body overrides this behavior 
 - Specify the 
 - 
Restart a SeaCat PKI
 - 
Create Root CA Certificate Trust List (CTL)
Use the initial CTL template rootca-ctl-init.json and copy that into
templates/rootca-ctl.json.IMPORTANT: Adjust the URL of the Root CA DC in the file.
curl -X PUT --url "${ROOT_CA_URL}/cits/rca/ctl" \ --header 'Content-Type: application/json' \ -d @templates/rootca-ctl-init.json.json - 
Create Root CA Certificate Revocation List (CRL)
Use the empty initial CRL template rootca-crl-init.json and copy that into
templates/rootca-crl.json.curl -X PUT --url "${ROOT_CA_URL}/cits/rca/crl" \ --header 'Content-Type: application/json' \ -d @templates/rootca-crl-init.json - 
Root CA is now configured and available for use.
 
Generate Enrolment Authority (EA) certificate¶
- 
Introduce a new tenant
in
etc/seacatpki.conf:[tenants] ids=TENANT_SUBCANote: You may reuse existing tenant, e.g. with Root CA. It is not possible to operate more EAs in the single tenant.
 - 
Specify a SeaCat PKI API base URLs
export ROOT_CA_URL=http://localhost:8080/TENANT_ROOT_CA export EA_URL=http://localhost:8080/TENANT_SUBCA - 
Generate Enrolment Authority verification private key
Choose one of following ECs:
Brainpool P-386 (
brainpoolP384r1)openssl ecparam -name brainpoolP384r1 -genkey -noout -out ea-verification-private-key.pemBrainpool P-256 (
brainpoolP256r1)openssl ecparam -name brainpoolP256r1 -genkey -noout -out ea-verification-private-key.pemNIST P-256 (
prime256v1,secp256r1)openssl ecparam -name prime256v1 -genkey -noout -out ea-verification-private-key.pem - 
Generate Enrolment Authority encryption private key
Choose one of following ECs:
Brainpool P-256 (
brainpoolP256r1)openssl ecparam -name brainpoolP256r1 -genkey -noout -out ea-encryption-private-key.pemNIST P-256 (
prime256v1,secp256r1)openssl ecparam -name prime256v1 -genkey -noout -out ea-encryption-private-key.pem - 
Configure keys in SeaCat PKI
in
etc/seacatpki.conf:[seacatpki:private_key:TENANT_SUBCA-verification-key] keyfile=${THIS_DIR}/ea-verification-private-key.pem tenants=TENANT_SUBCA [seacatpki:private_key:TENANT_SUBCA-encryption-key] keyfile=${THIS_DIR}/ea-encryption-private-key.pem tenants=TENANT_SUBCA - 
Restart a SeaCat PKI
 - 
Generate a EA CA Certificate Request.
Use the template ea-cacr.json and adjust. Fill values of
verification_key(TENANT_SUBCA-verification-key) andencryption_key(TENANT_SUBCA-encryption-key.curl -X PUT ${EA_URL}/cits/ea/ca-certificate-request \ --header 'Content-Type: application/json' \ -d @templates/ea-cacr.jsonNote the value of
pbidattribute from the response, it is a public object ID of a CA certificate request. - 
Download CA Certificate Request from EA
curl -o ea-cacr.coer ${EA_URL}/sa/<pbid>Note: If EA and Root CA shares the same tenant, download and upload steps can be skipped.
 - 
Upload EA CA Certificate Request to Root CA
curl -X PUT "${ROOT_CA_URL}/sa?family=cits&type=cacr" --upload-file ea-cacr.coerNote a
pbid. - 
Approve EA CA Certificate request in Root CA
Use the template rootca-ea-cacr-approve.json and adjust.
cacr,ca_certificate.curl -X PUT --url "${ROOT_CA_URL}/cits/rca/approve-ca-certificate-request" \ --header 'Content-Type: application/json' \ -d @templates/rootca-ea-cacr-approve.jsonNote a
pbidasea_cert_pbid, it refer to a newly created EA certificate. - 
Download certificates from Root CA
curl -o ea-cert.coer ${ROOT_CA_URL}/sa/<ea_cert_pbid> curl -o rootca-cert.coer ${ROOT_CA_URL}/cits/dc/getcert/<rca_certificate_digest>The Enrolment Authority certificate is stored in
ea-cert.coerfile.Note: If EA and Root CA shares the same tenant, download and upload steps can be skipped.
 - 
Upload the certificates into Enrolment Authority
curl -X PUT "${EA_URL}/sa?family=cits&type=cert" --upload-file rootca-cert.coer curl -X PUT "${EA_URL}/sa?family=cits&type=cert" --upload-file ea-cert.coer - 
Configure Enrolment Authority
in
etc/seacatpki.conf:[seacatpki:cits:ea:TENANT_SUBCA] certificate=<ea_certificate_pbid> encryption_key=TENANT_SUBCA-encryption-key verification_key=TENANT_SUBCA-verification-key trust_domain=<trust_domain_tenant>Use
ea_cert_pbidas a reference to a EA certificate from previous steps.encryption_keyandverification_keyare references to respective private keys configured above.Fill (optionally) also a name of tenant that contains
trust_domainthat this EA should be part of. - 
Add EA into the Root CA CTL
Use the template rootca-ctl.json or previous CTL template and adjust.
curl -X PUT --url "${ROOT_CA_URL}/cits/rca/create-certificate-trust-list" \ --header 'Content-Type: application/json' \ -d @templates/rootca-ctl.jsonSnipplet of what to add on CTL:
... { "add": { "ea": { "eaCertificate": "79C2F0762BC405D9", "aaAccessPoint": "http://pki.seacat.io/etsi-plugtest-bp-ea/cits/ea/authorization-validation", "itsAccessPoint": "http://pki.seacat.io/etsi-plugtest-bp-ea/cits/ea/enrolment" } } } ... - 
Restart a SeaCat PKI
 
Generate Authorization Authority (AA) certificate¶
- 
Introduce a new tenant
in
etc/seacatpki.conf:[tenants] ids=TENANT_SUBCA - 
Specify a SeaCat PKI API base URLs
export ROOT_CA_URL=http://localhost:8080/TENANT_ROOT_CA export AA_URL=http://localhost:8080/TENANT_SUBCA - 
Generate Authorization Authority verification private key
Choose one of following ECs:
Brainpool P-386 (
brainpoolP384r1)openssl ecparam -name brainpoolP384r1 -genkey -noout -out aa-verification-private-key.pemBrainpool P-256 (
brainpoolP256r1)openssl ecparam -name brainpoolP256r1 -genkey -noout -out aa-verification-private-key.pemNIST P-256 (
prime256v1,secp256r1)openssl ecparam -name prime256v1 -genkey -noout -out aa-verification-private-key.pem - 
Generate Authorization Authority encryption private key
Choose one of following ECs:
Brainpool P-256 (
brainpoolP256r1)openssl ecparam -name brainpoolP256r1 -genkey -noout -out aa-encryption-private-key.pemNIST P-256 (
prime256v1,secp256r1)openssl ecparam -name prime256v1 -genkey -noout -out aa-encryption-private-key.pem - 
Configure keys in SeaCat PKI
in
etc/seacatpki.conf:[seacatpki:private_key:TENANT_SUBCA-verification-key] keyfile=${THIS_DIR}/aa-verification-private-key.pem tenants=TENANT_SUBCA [seacatpki:private_key:TENANT_SUBCA-encryption-key] keyfile=${THIS_DIR}/aa-encryption-private-key.pem tenants=TENANT_SUBCA - 
Restart a SeaCat PKI
 - 
Generate a AA CA Certificate Request.
Use the template aa-cacr.json and adjust.
curl -X PUT ${AA_URL}/cits/aa/ca-certificate-request \ --header 'Content-Type: application/json' \ -d @templates/aa-cacr.jsonResponse
{ "result": "OK", "pbid": "etsi-plugtest-nist-aa2:d09833dafcdb1b7d44614b28500a2ee2eb50c94a918155023b68b65bd1862bb8", "fingerprint": "d09833dafcdb1b7d44614b28500a2ee2eb50c94a918155023b68b65bd1862bb8" } - 
Download CA Certificate Request from AA
curl -o aa-cacr.coer ${AA_URL}/sa/<pbid>This stores AA CA Certificate Request in
aa-cacr.coerfile.Note: If AA and Root CA shares the same tenant, download and upload steps can be skipped.
 - 
Upload CA Certificate Request to Root CA
curl -X PUT "${ROOT_CA_URL}/sa?family=cits&type=cacr" --upload-file aa-cacr.coerResponse:
{ "result": "OK", "pbid": "etsi-plugtest-nist-rca:d09833dafcdb1b7d44614b28500a2ee2eb50c94a918155023b68b65bd1862bb8" }Note a
pbidascacr_pbid. - 
Approve AA CA Certificate request at Root CA
Use the template rootca-aa-cacr-approve.json and adjust.
curl -X PUT "${ROOT_CA_URL}/cits/rca/approve-ca-certificate-request" \ --header 'Content-Type: application/json' \ -d @templates/rootca-aa-cacr-approve.jsonResult:
{ "result": "OK", "pbid": "etsi-plugtest-nist-rca:C7C6182511C8716C" }Note a
pbidasaa_certificate_pbid, it refer to a newly created AA certificate. - 
Download certificates from Root CA
You need to download the new AA certificate (1) and the Root CA certificate (2).
curl -o cert_aa.coer ${ROOT_CA_URL}/sa/<aa_certificate_pbid> curl -o cert_rca.coer ${ROOT_CA_URL}/cits/dc/getcert/<rca_certificate_digest>The Authorization Authority certificate is stored in
cert_aa.coerfile. The Root Certificate Authority certificate is stored incert_rca.coerfile.Note: If AA and Root CA shares the same tenant, download and upload steps can be skipped.
 - 
Upload certificates to SeaCat PKI
curl -X PUT "${AA_URL}/sa?family=cits&type=cert" --upload-file cert_rca.coer curl -X PUT "${AA_URL}/sa?family=cits&type=cert" --upload-file cert_aa.coer - 
Configure Authorization Authority
in
etc/seacatpki.conf:[seacatpki:cits:aa:TENANT_SUBCA] certificate=<aa_certificate_pbid> encryption_key=TENANT_SUBCA-encryption-key verification_key=TENANT_SUBCA-verification-key trust_domain=<trust_domain_tenant>Use
aa_certificate_pbidas a reference to a AA certificate from previous steps.encryption_keyandverification_keyare references to respective private keys configured above.Fill (optionally) also a name of tenant that contains
trust_domainthat this AA should be part of. - 
Add AA into the Root CA CTL
Use the template rootca-ctl.json or previous CTL template and adjust.
curl -X PUT --url "${ROOT_CA_URL}/cits/rca/create-certificate-trust-list" \ --header 'Content-Type: application/json' \ -d @templates/rootca-ctl.jsonA snipplet of that needs to be added to CTL:
... { "add": { "aa": { "aaCertificate": "8476936376DEE4DA", "accessPoint": "https://via.teskalabs.com/cits-otenv/v1.3/aa/authorization" } } } ... - 
Restart a SeaCat PKI
 
Trust List Manager Setup¶
Prerequisite: SeaCat PKI is installed, configured and stopped.
- 
Introduce a new tenant
in
etc/seacatpki.conf:[tenants] ids=TENANT_TLM - 
Specify a SeaCat PKI API base URL
export TLM_URL=http://localhost:8080/TENANT_TLM - 
Generate the TLM private/public key pair
Select one of the following EC curves:
Brainpool P-386 (
brainpoolP384r1)openssl ecparam -name brainpoolP384r1 -genkey -noout -out tlm-private-key.pemBrainpool P-256 (
brainpoolP256r1)openssl ecparam -name brainpoolP256r1 -genkey -noout -out tlm-private-key.pemNIST P-256 (
prime256v1,secp256r1)openssl ecparam -name prime256v1 -genkey -noout -out tlm-private-key.pem - 
Add a new private key into the configuration file
in
etc/seacatpki.conf:[seacatpki:private_key:TENANT_TLM] keyfile=${THIS_DIR}/tlm-private-key.pem tenants=TENANT_TLM - 
Start SeaCat PKI
 - 
Create self-signed TLM certificate
Use the template tlm.json and adjust if needed.
curl -X PUT "${TLM_URL}/cits/tlm/self-signed?tlm_private_key=TENANT_TLM" \ --header 'Content-Type: application/json' \ -d @templates/tlm.jsonNote the value of
pbidattribute from the response, it is a public object ID of a new certificate. - 
Configure a new TLM in SeaCat PKI configuration file
in
etc/seacatpki.conf:[seacatpki:cits:tlm:TENANT_TLM] certificate=<pbid>Specify the
pbidof the newly generated Root CA Certificate from a step above. - 
Restart a SeaCat PKI
 - 
Create TLM Certificate Trust List
Use the initial CTL template tlm-ctl-init.json.
IMPORTANT: Adjust the URL of the TLM in the file.
curl -X PUT --url "${TLM_URL}/cits/tlm/ectl" \ --header 'Content-Type: application/json' \ -d @templates/tlm-ctl-init.json - 
TLM is now configured and available for use.
 
Extending a trust domain with local configurations¶
You may need to manually extend the trust domain locally by Root CAs, EAs and/or AAs.
Eg. a trust domain of AA can be extended locally to reach EA when TLM is not present or is not yet updated.
Adding a local Root CA¶
[seacatpki:cits:trust:foobar]
...
local_rca:
    https://via.teskalabs.com/cits-otenv/v1.3/dc/getcert/D817CE980CF1FEC7
    https://via.teskalabs.com/cits-otenv/v1.3/dc
local_rca: the local EA config value has to start with local_rea, e.g. local_rca1 will work as well, which is the way how you can specify more than one locally added Root CAs.
The first line is an URI of the Root CA Certificate.
Possible values are HTTP or HTTPS URL, file:// and an absolute file system path.
PKI will download the certificate and store that in the trust domain database.
The second line is an URL of the Root CA Distribution Centre (DC), it is optional.
Adding a local EA¶
[seacatpki:cits:trust:foobar]
...
local_ea:
    https://via.teskalabs.com/cits-otenv/v1.3/dc/getcert/D817CE980CF1FEC7
    https://via.teskalabs.com/cits-otenv/v1.3/ea/authorization-validation
    https://via.teskalabs.com/cits-otenv/v1.3/ea/enrolment
local_ea: the local EA config value has to start with local_ea, e.g. local_ea1 will work as well, which is the way how you can specify more than one locally added EA.
The first line is an URI of the EA Certificate.
Possible values are HTTP or HTTPS URL, file:// and an absolute file system path.
PKI will download the certificate and store that in the trust domain database.
The second line is an URL of the EA Authorization validation endpoint (AA access point).
The third line is an URL of the EA Enrolment endpoint (ITS access point), it is optional.
Adding a local AA¶
[seacatpki:cits:trust:foobar]
...
local_aa:
    https://via.teskalabs.com/cits-otenv/v1.3/dc/getcert/D817CE980CF1FEC7
    https://via.teskalabs.com/cits-otenv/v1.3/aa/authorizaion
local_aa: the local AA config value has to start with local_aa, e.g. local_aa1 will work as well, which is the way how you can specify more than one locally added AA.
The first line is an URI of the AA Certificate.
Possible values are HTTP or HTTPS URL, file:// and an absolute file system path.
PKI will download the certificate and store that in the trust domain database.
The second line is an URL of the AA Authorization endpoint, it is optional.
Technical specification of a new C-ITS PKI¶
This questionnaire has to be filled by a C-ITS PKI provider prior PKI installation. TeskaLabs can provide reasonable defaults where possible based on standardisation and deployment experiences.
The TLM to which new Root CA certificate to be inserted¶
In case of EU TLM, the intended level (L0, L1, L2) should be defined according to a EU TLM CPOC Protocol. Also the name of Root CA certificate is to be assigned by CPA of CPOC.
Answer: __
Note: This pre-requisite is optional, TLM could be skipped or introduced later.
Requested components¶
- Number of Root Certificate Authority (RCA): __
 - Number of Enrollment Authorities (EA): __
 - Number of Authorization Authorities (AA): __
 
Typical C-ITS PKI contains 1 RCA, 1 EA and 1 AA. Number of EAs and AAs could be extended during the lifecycle of the PKI.
Tenant name¶
It may become a part of PKI URLs.
Answer: __
Example: croads_cz_l0
Base URL(s) of the PKI authorities¶
Answer: http://__
It could be the same for RCA, EA and AA or specific for each component.
It must start with http://
Root CA Certificate key curve¶
Select one of:
- Brainpool P-386
 - Brainpool P-256
 - NIST P-256
 
We recommend Brainpool P-386.
Root CA certificate¶
Use attached JSON template rootca.json.
Important information:
- Root CA certificate name, example 
0_My-New-Root-CA_L0 
Note: If Root CA certificate is to be introduced to TLM, the name has to comply with the TLM requirements.
EA certificate verification key curve¶
Select one for verification key:
- Brainpool P-386
 - Brainpool P-256
 - NIST P-256
 
We recommend Brainpool P-256.
EA certificate encryption key curve¶
Select one for encryption key:
- Brainpool P-256
 - NIST P-256
 
We recommend Brainpool P-256.
EA certificate request¶
Use attached JSON template ea-cacr.json.
Important information:
- EA certificate name
 
AA certificate verification key curve¶
Select one for verification key:
- Brainpool P-386
 - Brainpool P-256
 - NIST P-256
 
We recommend Brainpool P-256.
AA certificate encryption key curve¶
Select one for encryption key:
- Brainpool P-256
 - NIST P-256
 
We recommend Brainpool P-256.
AA certificate request¶
Use attached JSON template aa-cacr.json.
Important information:
- AA certificate name
 







