OCV Services
Introduction
OCV stands for 'Open Certificate validation'. For business applications relying on PKIs the process of trusting digital certificates is complex. It requires the ability to locate certificates from online resources in order to construct a valid certificate path to one or more trust anchors. Once a certificate path is successfully constructed it then needs to be subjected to a multi-step validation process, where many fields and extensions inside each certificate in the path are reviewed and validated according to a complex set of PKI rules.
The OCV Server provides all of the above functionality in a centralized manner. This allows business applications to delegate all of the responsibility for certificate path discovery and validation. This greatly simplifies development of business applications that rely on PKIs, by hiding all the inherent complexity.
The OCV takes part in the context defined by EFVS SC14 (Refernece model for eSignature Validation), following image is setting the context for OCV:
This chapter has been provided in order to understand the functionality provided by the OCV client available in T1C-JLIB (after activating the api-key for the OCV API).
Functional Scope
- complies with IETF RFC 5055 and RFC 3379 for delegated path discovery (DPD) and delegated path validation (DPV) of digital certificates
- Supports dynamic Delegated Path Discovery (DPD) even in complex bridge CA, mesh and cross-certification PKI topologies
- Supports full certificate validation using RFC 5280 and RFC 3379 validation algorithm, including validation of Key Usage, Extended Key Usage, Certificate Policies, Name validation, policy mapping and other related checks
- Supports revocation checking using advanced OCSP and CRL handling
- Provides ability to create multiple validation profiles each with their own final trust anchors, path building and validation settings
- Support historical certificate validation service
- High-performance architecture including caching of intermediate CA certificates and revocation info
- Strong security using the latest crypto-algorithms
Architecture - Component Overview
The following component diagram denotes a global overview of the OCV (Open Certificate Validation API) building blocks.
The solution exposes and uses for several use cases an CRL and OCSP service layer.
The OCSP Layer consists of the following components:
- Offline and online OCSP source
- Signature OCSP source
- CAdES, PAdES and XAdES source
The CRL layer consist of the following components:
- Offline and online CRL source
- JDBC source
- Signature OCSP source
- CAdES, PAdES and XAdES source
Client Integration
Supported Use Cases
The list of supported use cases will grown with upcoming releases, the T1C-JLIB supports:
- Request server generated challenge for authentication purpose
- Verify Signed Challenge for authentication purpose
- Validate Certificate Chain (OCSP and CRL check)
Interface
Modifier and Type | Method and Description |
---|---|
com.t1t.t1c.ocv.OcvChallengeRequest |
getChallenge(com.t1t.t1c.model.DigestAlgorithm digestAlgorithm) Returns the hash of a serverside-cached challenge in the requested algorithm |
com.t1t.t1c.ocv.OcvChallengeVerificationResponse |
verifyChallenge(com.t1t.t1c.ocv.OcvChallengeVerificationRequest request) Verifies the signed hash against the server challenge |
com.t1t.t1c.ocv.OcvCertificateChainValidationResponse |
validateCertificateChain(java.lang.String... certificates) Verifies a certificate chain |
API Activation
In order to active the OCV API, the api-key should be contracted with the OCV API.
To do so, you can contact: [email protected] or use the customer portal to request an api-key.
Upon configuration of the T1C-JLIB, an additional url should be provided:
LibConfig conf = new LibConfig();
conf.setEnvironment(Environment.DEV);
conf.setDsUri(DS_URI);
// Set the OCV URI here
conf.setOcvUri(OCV_URI);
conf.setGclClientUri(URI_T1C_GCL);
conf.setApiKey(API_KEY);
conf.setHardwarePinPadForced(false);
conf.setDefaultPollingIntervalInSeconds(5);
conf.setDefaultPollingTimeoutInSeconds(10);
conf.setSessionTimeout(60);
T1cClient t1cClient = new T1cClient(conf);
This configures the OCV URI for the T1C-JLIB instance used in your Java application. Note that the api-key must be enabled in order to do so (the service will respond with an 'unauthenticated' response).
Examples
OCV Client Instance
In order to obtain an OCV client instance, you can call the following function:
IOcvClient ocvClient = t1Client.getOcvClient();
Validate Certificate Chain (OCSP and CRL check)
The certificates received can be validated against the CA (Certificate Authority). In order to do so, the T1C-JLIB uses the OCV API to perform:
- validation of certificate expiration
- validation of the certificate chain
- OCSP validation of the certificate chain
- CRL validation of the certificate chain
The following function can be called in order to perform the aforementioned validation:
ocvClient.validateCertificateChain("leafCertificate", "intermediateCertificate", "rootCertificate");
The certificate order is of great importance; the order is 0-based, and the first certificate should be a leaf certificate, followed by one or more intermediates and ending with the root-certificate.
As an example; you can see how this works for Belgian eID on Belgian eID Container)
We first retrieve the following certificates: root, citizen and authentication certificates:
IBeIdContainer container = t1cClient.getBeIdContainer(reader.getId());
GclBeIDAllCertificates certificates = container.getAllCertificates();
Now we can create the body in order to call the certificate validation function:
OcvCertificateChainValidationResponse response = ocvClient.validateCertificateChain(
certificates.getAuthenticationCertificate().getBase64(),
certificates.getCitizenCertificate().getBase64(),
certificates.getRootCertificate().getBase64());
The certificate validation response will contain the validation info for OCSP and CRL; the status must be true:
com.t1t.t1c.ocv.OcvCertificateChainValidationResponse
Name | Description | Example Value | Type |
---|---|---|---|
ocspResponse |
The OCSP response | See below | com.t1t.t1c.ocv.OcvOcspResponse |
crlResponse |
The CRL response | See below | com.t1t.t1c.ocv.OcvCrlResponse |
com.t1t.t1c.ocv.OcvOcspResponse
Name | Description | Example Value | Type |
---|---|---|---|
status |
The OCSP status | true | java.lang.Boolean |
oscpLocation |
The OCSP location | "http://ocsp.eid.belgium.be/2" | java.lang.String |
com.t1t.t1c.ocv.OcvCrlResponse
Name | Description | Example Value | Type |
---|---|---|---|
status |
The CRL status | true | java.lang.Boolean |
version |
The CRL version | "2" | java.lang.String |
signatureAlgorithm |
The signature algorithm | "RSA_SHA1" | java.lang.String |
issuerCertificate |
The issuer certificate | "C=BE,CN=Citizen CA,SERIALNUMBER=201603" | java.lang.String |
crlLocations |
The CRL locations | ["http://crl.eid.belgium.be/eidc201603.crl"\] | java.util.List<java.lang.String> |
productionDate |
The production date | "Tue Nov 29 15:51:08 UTC 2016" | java.lang.String |
Authenticate with back-end generated Challenge
The OCV API exposes endpoints to generate a random challenge, and to validate the signed challenge hash. The following digest algorithms are supported:
- MD5
- SHA1
- SHA256
- SHA512
The following flow has been implemented in order to authenticate a user with a smart card. The code example denotes how to use the T1C-JLIB to do so in 3 steps:
- generate challenge
- sign challenge hash
- validate signed challenge hash
Get Authentication Challenge
First we need to retrieve a challenge hash form the OCV API:
IOcvClient ocvClient = t1cClient.getOcvClient();
OcvChallengeRequest hashtoAuthenticate = ocvClient.getChallenge(DigestAlgorithm.SHA256);
An example response:
com.t1t.t1c.ocv.OcvChallengeRequest
Name | Description | Example Value | Type |
---|---|---|---|
digestAlgorithm |
The digest algorithm | "SHA256" | java.lang.String |
hash |
The hash to sign | "ZMUv04O9A/NzNetkuwVY+9bbYlyBYvtCyDSka4dwaQ0=" | java.lang.String |
Sign Challenge Hash
The hash returned should be send to the T1C-GCL (local instance communicating with eID card in the smart card reader). When the user doesn't have a pin-pad reader, the pin dialog must be shown from the custom UI page in order to capture the pi (in order to prevent MIT attack the communication with T1C-GCL is always over https).
BeIdContainer container = t1cClient.getBeIdContainer(reader);
String authenticatedData = container.authenticate(
//data
hashtoAuthenticate.getHash(),
//Digest algorithn
hashtoAuthenticate.getDigestAlgorithm(),
//PIN
"1234"
);
The data property is the signature of the challenge hash received from the OCV API.
Verify Authentication Challenge Signature
As a last step we need to verify the signature received in the previous step. We can do this using an OCV validation endpoint.
OcvChallengeVerificationResponse response = ocvClient.verifyChallenge(new OcvChallengeVerificationRequest()
.withBase64Certificate(container.getAuthenticationCertificate(false).getBase64())
.withBase64Signature(authenticatedData)
.withHash(hashtoAuthenticate.getHash())
.withDigestAlgorithm(hashtoAuthenticate.getDigestAlgorithm()));
An example response:
com.t1t.t1c.ocv.OcvChallengeVerificationResponse
Name | Description | Example Value | Type |
---|---|---|---|
digestAlgorithm |
The digest algorithm | "SHA256" | java.lang.String |
hash |
The hash to sign | "ZMUv04O9A/NzNetkuwVY+9bbYlyBYvtCyDSka4dwaQ0=" | java.lang.String |
result |
The result of the authentication | true | java.lang.Boolean |
When the result is 'true', the user has been authenticated correctly using a server generated challenge.