Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This documentation covers the technical aspects of the remote signing services, including the validation service. The three main services are enterprise signature, eSigning - person signing and validation.

The signing service is an implementation of version 1.0.4 of the specification created by the cloud signing consortium (CSC). Documentation is available here. The Buypass remote signing services also include a validation service, which is out of scope for the CSC specification but follows the same design and implementation principles.

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

  • 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();
}

Table of Contents

Table of Contents

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

Signing

The signing service currently implements only a mandatory subset of the endpoints specified in the CSC specification.

Authorization

Use of the centrally stored private signing key to create a signature must be authorized by presenting a SAD ( Signature Activation Data) to the signing API.

The SAD must be obtained from the OIDC server using the following URL:

  • Test environment : https://auth.tsp.test4.buypass.no/auth/realms/enterpriseid/protocol/openid-connect/token?_tlsclientauth=1

  • Production environment :  https://auth.tsp.buypass.no/auth/realms/enterpriseid/protocol/openid-connect/token?_tlsclientauth=1

Example:

$ curl -X POST https://auth.tsp.test4.buypass.no/auth/realms/enterpriseid/protocol/openid-connect/token?_tlsclientauth=1

  • H "Content-Type application/x-www-form-urlencoded"

  • d "grant_type=client_credentials&client_id=SAD

The TLS connection in this case requires client authentication, which must be set up using the PKCS#12 keystore received when ordering the Enterprise Certificate for signing.

Provided the TLS connection is successful, the HTTP response from the OIDC server returns contains a JSON body like this:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5c...",
"expires_in": 60,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR.....",
"token_type": "bearer",
"not-before-policy": 0,
"session_state": "69ab03e6-9ce4-4085-9e84-80310d55de1a",
"scope": ""
}

The value of the access_token attribute (a signed JWT) is the SAD.

Endpoints

Request

The signing request has the format:

{
"SAD": "eyJhbGciOiJSUzI1NiIsInR5cCIg.....",
"credentialID": "123456",
"hash": [
"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
],
"signAlgo": "RSA",
"signAlgoParams" : "string",
"hashAlgo": "SHA-256",
"clientData" : "string"

}

The attributes have the following meaning:

  • SAD : The access token authorizing the use of the signing key - described above

  • credentialID : Identifier of the signing key to be used. This attribute is currently not in use, as the credential ID is included in the SAD.

  • hash : An array of Base64-encoded hash values to be signed. These should be raw document hashes, as the signing service wraps each hash in a DigestInfo structure before signing.

  • signAlgo : The signing algorithm. Currently only RSA is supported. The algorithm name is case-insensitive, and may alternatively be given as an Object Identifier.

  • signAlgoParams : Not used.

  • hashAlgo : The hash algorithm. May be given by name (e.g. "SHA-256") or Object Identifier.

  • clientData : Not used.

Note that in addition to the SAD, which is included in the request body, the "Authorization" header with the Bearer token containing the API scopes must be set.

See section 11.9 in https://cloudsignatureconsortium.org/wp-content/uploads/2019/07/CSC_API_V1_1.0.4.0.pdf for further details

Response

The signing response has the format : 

Code Block
{
"signatures": [
 "string"
 ]
}

The attributes have the following meaning:

  • signatures: An array of Base64-encoded signatures, in the same ordering as the hash values in the request.

See section 11.9 in https://cloudsignatureconsortium.org/wp-content/uploads/2019/07/CSC_API_V1_1.0.4.0.pdf for further details.

Child pages (Children Display)