BCSS - validation

Abstract

The validation service enables the user to validate existing signatures. It also returns all relevant revocation- and certificate chain information. This information may be stored together with the signature and enables the signature to be validated at a later time, even if the CA is out of service and revocation information is no longer available online. The validation service supports signatures created by certificates issued by most major Certificate Authorities.

The remote enterprice and person signing services signs hash values supplied through the signing API, provided a valid token authorizing access to the centrally stored private signing key is also supplied. 

The signing algorithms supported by the services is RSA.

 

 

Authentication - access to Signing Service

To gain access to the remote signing services you need to be authenticated. Authentication is performed by sending a signed JWT to the Buypass enterprise OIDC server. The JWT must be signed with a merchant certificate.

The response from the OIDC server is a json with an access_token. This token should be provided with each request to the remote signing service as a header property with the key 'Authorization' and value 'Bearer TOKEN'. The access_token expires after a relatively short period. To be able to continue to send requests to the remote signing service, a new token must then be acquired.

Scopes

There are three available scopes

  1. The service scope, this scope gives access to the api

  2. The credential scope, this scope gives access to the signing service

  3. The validation scope, this scope gives access to the validation services

All requests to the remote signing api should contain a token with at least the service scope. If the signing- or validation services are requested, the token needs either the credential or the validation scope in addition. Clients who use both signing and validation services may requests all three scopes for their token and use it for all services.

Servers

This is an example for access to enterprise signing service - further api documentation see https://buypassdev.atlassian.net/wiki/spaces/DEVSPACE/pages/2999910401 or https://buypassdev.atlassian.net/wiki/spaces/DEVSPACE/pages/2999877634

  • For the test environment, the oidc services are accessible at https://auth.tsp.test4.buypass.no/auth/realms/enterpriseid

  • For production, the oidc services are accessible at https://auth.tsp.buypass.no/auth/realms/enterpriseid

Example code

$ curl -X POST https://auth.tsp.test4.buypass.no/auth/realms/enterpriseid/protocol/openid-connect/token
-H "Content-Type application/x-www-form-urlencoded"
-d "grant_type=client_credentials\
&scope=service%20credential%20validation\
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer\
&client_assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiJiNWE3YjYwZi00ODM4LTQxOTktODg5Zi1kYTA5ZjBlZDE2YWUiLCJpYXQiOjE2MDMyMDIzMzksInN1YiI6InJlbW90ZS1zaWduYXR1cmUtY2xpZW50LTc3ODg5OSIsImlzcyI6InJlbW90ZS1zaWduYXR1cmUtY2xpZW50LTc3ODg5OSIsIm5iZiI6MTYwMzIwMjMzOSwiZXhwIjoxNjAzMjA1OTM5LCJhdWQiOiJodHRwczovL2F1dGgudHNwLnRlc3Q0LmJ1eXBhc3Mubm8vYXV0aC9yZWFsbXMvZW50ZXJwcmlzZWlkIn0.g7zG9EZzMg07yw3auKY5eAtXOs_atIYN6-XstoOctfgibFVTompYHdX20H6TaTYc2HBMC8sYkO0qNpd4H9sCKf2MrmMCZ4nZRvcOlMrl3UpEv01-GkwxnR8hkA11ciQtKNHZ5qtClzaaswTWKZ7RN2Xr41p3kXeD4g40KTwdFAgzBwcgZoXN23hjeOkpxhll2mI8zSLBf-COMzuq0DnLXYIkzyvcqDcs8xu4Wo7wzyF5rZHCZ4i7cu1_Ju17Ijn-kmrMyXimQ15rr-GyqmwwJmvuCZ6eogUtBIcx1IlDfkq9o0ykoEALp-hPna5aUb96jSn0RCUnI_v4FZ_-GA0Y0g"

The client requesting authentication needs to set the correct scopes after &scope=. The scopes should be space separated and URL-encoded.

The client also need to construct a valid client_assertion, which is a base 64 encoded signed jwt. There are numerous libraries that are capable to do this. Here are some details regarding the assertion

Assertion header

{
  "typ": "JWT",
  "alg": "RS256"
}

These values are currently fixed.

Assertion payload

{
  "jti": "d90854d1-7df9-4541-b0df-bdca97209065",    // A unique requestid
  "iat": 1574940763,                                // Issued at 'seconds since epoch'. The client should provide 'now'
  "sub": "remote-signature-client-778899",          // The id of the client
  "iss": "remote-signature-client-778899",          // The id of the client
  "nbf": 1574940763,                                // Not valid before 'seconds since epoch'. The client should provide 'now'
  "exp": 1574944363,                                // Expiry date of the refresh token - not that relevant in this flow. Can be set til 'now' + 1 hour
  "aud": "https://auth.tsp.test4.buypass.no/auth/realms/enterpriseid"   // URL of the OIDC server
}

Java example

In java the client assertion can be created with the following code:

private String createSignedJWT()
    KeyStore keystore = ...
    keystore.load(...);
    PrivateKey key = (PrivateKey)keystore.getKey(...);
 
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key.getEncoded());
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PrivateKey privKey = kf.generatePrivate(keySpec);
 
    JwtBuilder builder = Jwts.builder()
        .setHeaderParam("typ", "JWT")
        .setId(createUniqueId())
        .setIssuedAt(now())
        .setSubject("remote-signature-client-778899")
        .setIssuer("remote-signature-client-778899")
        .setNotBefore(now())
        .setExpiration(nowPlusOneHour())
        .setAudience("https://auth.tsp.buypass.no/auth/realms/enterpriseid")
        .signWith(RS256, privKey);
 
    return builder.compact();
}

 

 


 

Validation

Endpoints

Minimal request

The minimal request to validate a signature is this

{
  "certificateChain": {
    "signingCertificate": {
      "certificate": "base64EncodedCertificate"
    }
  },
  "hash": "base64EncodedHash",
  "hashAlgo": "hashAlgorithmUsed",
  "signAlgo": "signingAlgorithmUsed",
  "signature": "base64EncodedSignature"
}

Given a minimal request, the validation service will, if possible, construct the complete certificate chain and fetch all available revocation data needed to validate the signing certificate and verify the signature.

For validation within the validity period of the signing certificate, the minimal request will be sufficient. For long term validation, a full request will be necessary. Se the section below for details.

When no ocsp or crl is provided, the remote signing api will validate that the certificates are vaild now. If the certificate has been revoked between the signing time and validation time, the validation api will still declare the signature for invalid, since it is impossible to determine whether the certificate was valid at the time the signature was created. 

Full request

A full request contains all information necessary to validate a signature. It is not necessary to fetch any information online from the CA and validation can be performed even if the CA is no longer operational.

A full request would contain all the given values

{
  "certificateChain": {
    "signingCertificate": {
      "certificate": "base64EncodedCertificate",
      "ocsp": "base64EncodedOcspResponse"
    },
    "intermediateCertificates": [
      {
        "certificate": "base64EncodedCertificate",
        "crl": "base64EncodedCrl"
      }
    ],
    "trustAnchor": {
      "certificate": "base64EncodedCertificate"
    }
  },
  "hash": "base64EncodedHash",
  "hashAlgo": "hashAlgorithmUsed",
  "signAlgo": "signingAlgorithmUsed",
  "signature": "base64EncodedSignature",
  "signatureTime": "2019-12-13T19:32:17.696Z"
}

  • The certificate chain should consist of all certificates in the chain, from the signing certificate to the root certificate. If there are more than one intermediate certificate, the api expects them to be ordered.

    • A signing certificate should consist of two elements

      • A base64 encoded representation of a X.509 certificate

      • A base64 encoded representation of a valid ocsp response, obtained at or near the signing time. 

    • An intermediate certificate should consist of a list where each entry consists of two elements

      • A base64 encoded representation of a X.509 certificate

      • A base64 encoded representation of a valid crl generated at or near the signing time.

    • A trusted root certificate should consist of one element

      • A base64 encoded representation of a X.509 certificate. This root certificate must be a trusted certificate in the remote signing services. In practical terms, this means that the root certificate must be in the list of trusted roots in the Java Runtime.

  • The hash that should be validated must be provided. It should be a base 64 representation of the hash which the signature is over

  • The hash algorithm used must be provided. The algorithms currently supported are MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512. This parameter is case insensitive, and the algorithm name may be given with or without a dash. The OID of the algorithm is also possible to use.

  • The signature must be provided. It should be a base 64 representation of the raw signature.

  • The signature algorithm used must be provided. The only algorithm currently supported is RSA.

  • The time which the signature was created is optional. If it it not provided the remote signing service treats the signature time as 'now'. Several parts of the validation is performed under the presumption that the given signature time is correct. If an incorrect signature time is provided, the result cannot be trusted.

Response

Whether a full or minimal validation request is supplied, the remote signing service always returns a full response:

{
  "validationStatus": {
    "mainIndication": "PASSED",
    "subIndication": null
 },
  "validationTimeInfo": {
    "signatureTime": "2019-12-13T19:31:03.575Z",
    "validationTime": "2019-12-13T19:31:03.575Z"
  },
  "certificateChain": {
    "signingCertificate": {
      "certificate": "base64EncodedCertificate",
      "ocsp": "base64EncodedOcspResponse"
    },
    "intermediateCertificates": [
      {
        "certificate": "base64EncodedCertificate",
        "crl": "base64EncodedCrl"
      }
    ],
    "trustAnchor": {
      "certificate": "base64EncodedCertificate"
    }
  }
}

 

  • Validation status should be according to ETSI TS 119 102-1,  specifically chapter 5 - Validation.

  • Main indication is either PASSED, FAILED or INDETERMINATE.

    • PASSED is only returned if all necessary information is provided or obtained and all elements are validated to be correct.

    • FAILED is returned if the service is able to determine that some part of the hash, signature or certificate chain is wrong. The reason is then given in the sub indication.

    • INDETERMINATE is returned if the service is lacking information to determine whether the signature is valid or not. The reason is then given in the sub indication.

    • Sub indication will try to indicate the reason to the failed or indeterminate status. If there exists more than one problem, only the first is returned.

  • Validation time info consists of two values, signature- and validation time.

    • Signature time is when the signature was created. If no value is provided in the request, the system set this value to the time of validation.

    • Validation time is when the validation occurred.

  • The certificate chain consist of all certificates in the chain, from the signing certificate to the root certificate. If there are more than one intermediate certificate, thy will be ordered.

    • A signing certificate consist of two elements

    • A base64 encoded representation of a X.509 certificate

    • A base64 encoded representation of a valid ocsp response from the time of the signature

    • An intermediate certificate should consist of a list where each entry consists of two elements

      • A base64 encoded representation of a X.509 certificate

      • A base64 encoded representation of a valid crl from the time of the signature

    • A trusted root certificate should consist of one element

      • A base64 encoded representation of a X.509 certificate. This root certificate is a trusted certificate in the remote signing services