Securing a Connection

Securing your Connection and Data

This page will help you to:

  • Understand the components required to secure a connection
  • Provide examples of how to generate the required JSON Web Token (JWT)
  • View fields to be provided in the JWT header and payload
  • Message level encryption

Security Overview

Today, API Security is a key priority for protecting important data, especially within Financial Services. Here at HSBC, when it comes to data security, our market leading API Developer platform goes further than just industry best practice.

The diagram below illustrates how Authentication, Authorisation, TLS and Message Level Encryption combined, stack up to provide you with world class API Security.

API security

The following measures and their components are required to establish a secure connection between HSBC the API consumer:

Category Definition Components
Transport Layer Security HTTPS Connection (TLS) SSL Certificate
Digital Identity
Client/Partner's Platform Identification
Message Level Encryption Private Key & Public Keys for message encryption
API Authentication & Authorization The Client/ Partner's Platform Profile ID - Provided by HSBC
Customer ID - Unique ID of Customer on Partner's Platform -Provided by Partner's Platform
Associated Account's ID
Signed and Base64 encoded JWT (JWS) - created by the client/ partner

Here is an example of an example of an HTTP(s) Request

HTTP Request

Key

Description

Example Value

Version 3 (EDGE) Prior to Version 3

Header

 

Authorization

JSON Web Token (See: Authentication)

JWS asdf1234asdf1234.1234asdfqwer1234.qwerqwerqwer123412341234
X-HSBC-Trade-Finance-Token
X-HSBC-Request-Correlation-Id Unique Identifier for each request, format as per uuid.  65535c2e646a499d91da-6af957df3f78 65535c2e-646a-499d-91da-6af957df3f78
X-HSBC-Request-Idempotency-Key Value same as X-HSBC-Request-Correlation-Id, only required for POST requests N/A
X-HSBC-countryCode ISO 3166 Alpha-2 Country Code SG
Content-Type

Content-Type of Request

application/json
Body Base64 String

Base64 encoded string consisting RAW Request Content encrypted by bank's public key

From Version 3 onwards, a payload wrapper is added to surround the base64 encoded string 

{"encryptedRequestBase64": "eyJraWQiOiJndGUtY2xpZW50IiwiZW5jIjoiQTEyOEdDTSIsImFsZyI6IlJTQS1PQUVQ..."} eyJraWQiOiJndGUtY2xpZW50IiwiZW5jIjoiQTEyOEdDTSIsImFsZyI6IlJTQS1PQUVQ...

 

Here is an example of an example of an HTTP(s) Response

HTTP Response

Description

Example Value

Version 3 (Edge) Priori to Version 3
200 OK/ 201 Created

Encrypted Response

{"encryptedResponseBase64: "eyJraWQiOiJndGUtY2xpZW50IiwiZW5jIjoiQTEyOEdDTSIsImFsZyI6IlJTQS1PQUVQ..."} eyJraWQiOiJndGUtY2xpZW50IiwiZW5jIjoiQTEyOEdDTSIsImFsZyI6IlJTQS1PQUVQ...
Decrypted Response
{
  "data": {
    %responseData%
  },
  "meta": {
    "totalItems": 1
  }
}
{
  "code": "EMKT200",
  "message": "Success",
  "repliedTime": "2024-07-17 07:04:58",
  "correlationId": "lsis5atgjjk6wmj0mwndpjelx0varxxa",
  "responseData": {},
  "errorDetails": null
}
400 Bad Request Requester Side Errors
{
    "type": "/problem-details/types/validation-errors",
    "title": "Fields invalid",
    "status": "400",
    "detail": "data.invoices[0].externalInvoiceId must not be null.",
    "instance": "86838151-4acb-42ae-a81c-4edc0648d3b5",
    "errorDateTime": "2023-08-27T21:17:45.710Z"
}
eyJraWQiOiJndGUtY2xpZW50IiwiZW5jIjoiQTEyOEdDTSIsImFsZyI6IlJTQS1PQUVQ...

401 Unauthorized

Authorization credentials are missing or invalid.

Details

{
  "title": "Unauthorized , Invalid credentials.",
  "instance": "c3f8c0c3-7b06-4fc0-8d8d-b0998b0334b8",
  "status": 401,
  "type": "/authn-error/code/EDSPER2002", 
  "errorDateTime": "2024-03-11T05:28:47Z",
  "detail": "Unauthorized , Invalid credentials."
}
403 Forbidden Failed in Authorization of requested resource
{
  "type": "authz-error/code/ERRAUTHZ2005",
  "title": "Access Denied",
  "status": "403",
  "detail": "Entitlement Check failed.",
  "instance": "3D56A807-66DA-488A-BB15-370DB613D6B2",
  "errorDateTime": "2023-05-05T08:22:05.857880"
}
404 Not Found Empty resource/resource not found. {"encryptedResponseBase64: "eyJraWQiOiJndGUtY2xpZW50IiwiZW5jIjoiQTEyOEdDTSIsImFsZyI6IlJTQS1PQUVQ..."} eyJraWQiOiJndGUtY2xpZW50IiwiZW5jIjoiQTEyOEdDTSIsImFsZyI6IlJTQS1PQUVQ...
500 Internal Server Error The request failed due to an internal error.
{
  "type": "/problem-details/types/internal-server-error",
  "title": "Internal Server Error",
  "status": "500",
  "detail": "Internal Server Error.",
  "instance": "1d9294e7-20ea-4c34-9a89-c18a47254e8e",
  "errorDateTime": "2021-09-29T11:42:52.332Z"
}
503 Service Unavailable The request failed due to an internal error.
{
  "type": "/problem-details/types/internal-server-error",
  "title": "Service Unavailable.",
  "status": "503",
  "detail": "Service Unavailable.",
  "instance": "1d9294e7-20ea-4c34-9a89-c18a47254e8e",
  "errorDateTime": "2021-09-29T11:42:52.332Z"
}

Transport Layer Security

To encrypt the communication, the connection between the partner and HSBC uses Transport Layer Security (TLS) via HTTPS as a security protocol. TLS is a cryptographic protocol designed to provide communications security over a computer network.

When the partner requests a HTTPS connection to HSBC, a Digital Certificate is required. This certificate contains the cryptography needed to begin the automatic Secure Sockets Layer (SSL) handshake which involves the generation of shared secrets to establish a uniquely secure connection between the partner and HSBC.

Please ensure your organisation has a valid Digital Certificate from a recognised Certificate Authority before attempting connectivity to our APIs.

TLS

Message Level Encryption

Message Level Encryption (MLE) ensures Data privacy of messages either in transit or at rest and involves a PGP handshake and encryption key exchange.

HSBC uses Message Level Encryption for our Corporate and Institutional APIs to ensure the highest level of security is applied to the data exchanged by our APIs.

Public key encryption involves a pair of keys known as a public key and a private key. These keys are assigned to an entity that needs to authenticate its identity electronically, or to sign or encrypt data. Each public key is published and the corresponding private key is kept secret. Data that is encrypted with the public key can only be decrypted with the corresponding private key.

Public key cryptography enables encryption, decryption and non-repudiation. HSBC's APIs support asymmetric encryption that uses a public key to encrypt data and a private key to decrypt data. The public key is available in a trusted certificate, whereas the private key is confidential and not shared.

For Message Encryption purposes, both your organisation and HSBC will need to exchange Public Keys so both parties can decrypt and encrypt messages via the API communication.

We know that MLE carries an overhead, as both parties need to encrypt and decrypt both request and response messages, however this practice has the important advantage of non-repudiation, giving assurance to both sender and receiver that the message has not been modified.

MLE

PGP Encryption

PGP is an encryption program that provides cryptographic privacy and authentication for data communication. PGP is used for signing, encrypting, and decrypting texts, e-mails, files, directories, and whole disk partitions and to increase the security of e-mail communications.

What is the purpose?

For API Message Encryption purposes, the Public PGP Keys have to be exchanged between the API Consumer (Client) and HSBC the API Provider (HSBC).

Where to get a set of PGP keys?

Clients can generate their own Private Key / Public Key pair using a key generation tool such as GnuPG or GPG.

Public PGP Key Specification:

  1. Signing algorithm: 2048-bit
  2. RSA Hashing algorithm: SHA-256

Once your Certificate is ready, contact your HSBC Client Integration contact to trigger the Key Exchange Procedure.

How to use the PGP keys?

The Client uses HSBC's Public Key to encrypt a message every time it sends to HSBC. The Client verifies HSBC's digital signature every time a message is received from HSBC. HSBC uses the Client's Public Key to do the same upon messages sent and received from the Client.

For security purposes, HSBC's Public Key is renewed every year and a Certificate Renewal process will be triggered.

Key Storage and Duration of Validity
Component Storage Validity
Client's Private Key The Private Key should be maintained and handled with the most secure approach possible. The most common and yet secure approach is: key password - Do not save the password in plain text or hard-coded in an application. We recommend to encrypt it by any Password Encryption Tools/ key storage - Store inside a password-protected key repository, such as JKS or PKCS12 keystore. The Keystore password should also be encrypted. There is no Validity Period. However, if the Client suspects there is a chance that the key is leaked, or any other security reason, a new Private Key and its associated Public Key should be generated.
Client's Public Key Since the Public Key is publicly distributed, a moderately secure storage approach is acceptable. The Client can store the physical file in any machine's file system, or for centralised key management - store all keys and certificates in one single key repository. For a self-signed PGP Public key, the same condition as above applies. However, the validity period of a CA-signed Certificate is depended on the purchase plan of the issuing CA. The most common standard is 1 to 2 years.
HSBC's Public Key Same as above. The validity period is usually 1 Year plus 1 to 2 months extra. The extra period is a buffer to enable a client to switch a "to-be-expired" certificate to a new one during the PGP Key Renewal Process.

Digital Identity

Digital Signature is used to ensure that your API requests are not tampered with and originate from the expected source. It composes of:

  • Message Level Encryption
  • API Authentication and authorisation
Digital Identity

API Authentication - JWT Validation

API Authentication is performed using a signed JSON Web Token (JWT). The token must be provided in the header of the HTTP request every time you invoke HSBC's API services. This ensures only authorised and pre-approved organisations can access and utilise our API services.

The JWT is generated by the partner, not provided by HSBC. There are many utilities available that can provide JWT generation and validation logic for all commonly used programming languages. The following example uses the "io.jsonwebtoken" java library.

Building the JWT

What you will need:

Client/ Partner Private Encryption Key - for signing the JSON Web Token your system generated

Client/ Partner Public Encryption Key alias - The Public Key should be shared with HSBC as part of the client/ partner on-boarding process.

Client/ Partner Profile ID - The identifier HSBC provided you during the on-boarding process.

Code example

The below code provides a JWT example in Java:

   public static String generateAuthToken(String apiSchema, String clientProfileId, String onBehalfOf, String requestPayload, List<PGPPrivateKey> clientPgpPrivateKeys) {
        System.out.println("#a. Generating Auth Token...");
        String token = new String();
        PGPPrivateKey clientPgpPrivateKey = clientPgpPrivateKeys.get(0);
        try {
            System.out.println("#a.1. Using HashMap to build token structure...");
            // header
            Map<String, Object> headers = new HashMap<String, Object>();
            headers.put("kid", Long.toHexString(clientPgpPrivateKey.getKeyID()).toUpperCase());
            headers.put("typ", "JWT");
            headers.put("ver", "1.0");
            headers.put("alg", TOKEN_ALG);

            // claims
            Map<String, Object> claims = new HashMap<String, Object>();
            claims.put("jti", UUID.randomUUID().toString());
            claims.put("iat", System.currentTimeMillis() / 1000);
            claims.put("sub", clientProfileId); //API Profile ID Bank Assigned to you during on-boarding
            if (apiSchema == "EDGE") {
                claims.put("aud", "baas");
                // Obo, optional, only used when an API request is send on behalf of an End Customer
                if (onBehalfOf != null) {
                    Map<String, Object> obo = new HashMap<String, Object>();
                    obo.put("sub", onBehalfOf); //End Customer ID, provided by your platform during on-boarding
                    claims.put("obo", obo);
                }
            } else if (apiSchema == "GTRF") {
                claims.put("aud", "GTRF.MKT");
            }

            // print token object
            printAuthToken(headers, claims);


            System.out.println("#b.Preparing Auth Token Signature by converting Client Private Key from PGP to RSA: ");
            PrivateKey clientRsaPrivateKey = new JcaPGPKeyConverter().getPrivateKey(clientPgpPrivateKey); //Convert PGP Key to RSA Key
            System.out.println("#b.1. RSA Key for token signing:\n" + clientRsaPrivateKey.toString() + "\n");
            System.out.println("#c. Generating token using jwtBuilder: ");
            JwtBuilder jwtBuilder = Jwts.builder().setHeader(headers).setClaims(claims).signWith(clientRsaPrivateKey, SIGNATURE_ALG);
            token = jwtBuilder.compact();
            System.out.println("#c.1 Generated Token:\nJWS " + token);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (PGPException e) {
            e.printStackTrace();
        }
        return token;
    }

Fields in the JWT Header

The below table defines the fields (“claims”) that should be put inside the JWT header:

Code Name Type Mandatory Description Example
typ Token Type String Yes MUST set this to “JWT” "JWT"
kid Key ID Long.toHexString Yes Public Key Id which HSBC uses to verify JWT signature. HSBC reads the public key by this key ID, from the PGP key file provided by our client/ partners, to verify JWT signature. "900864F8C11EB743"
alg Signing Algorithm String Yes Algorithm to verify the signature on the token. The following algorithms are supported: RS256, RS384, RS512, PS256, PS384, PS512. "PS256"
ver Version String Yes HSBC private claim. Currently the partner MUST set it as "1.0". "1.0"

Note: We recommend the PS256, PS384, and PS512 algorithms over the other RSA algorithms. The PKCS#1.5 padding scheme (RS256, RS384, and RS512) does not provide the desired level of security and generally should be replaced by the PSS padding scheme.

Example structure:

{
    "typ": "JWT", 
    "kid": "A9248D0E4A463426",
    "alg": "PS256"
    "ver": "1.0"
}

Fields in the JWT Payload

The below table defines the fields (“claims”) that should be put inside the JWT payload:

Code Name Type Mandatory Description Example
jti JWT ID String Yes Case sensitive unique identifier of the token even among different issuers. There is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. The "jti" claim can be used to prevent the JWT from being replayed. The "jti" value is a case-sensitive string. "74760410-f963-11e8-b2a3-1bb26e1e5b69"
iat Issued At Long Yes Identifies the time at which the JWT was issued. The value must be a NumericDate. 1565150776
sub Subject String Yes Identifies the who send the request. MUST provide "Client/ Partner Profile ID" value "TAAS000000001"
obo.sub OnBehalfOf String No Identifies the the request is being sent on-behalf of which customer "customer001"
aud Audience String Yes Identifies the recipients that the JWT is intended for. Always "taas" or "baas"  "taas"
payload_hash Payload hash value String Yes Hashing value of the HTTP request payload body. This is used for Mule policy to do validation "1dab559f1f4bf4f3ca..."
payload_hash_alg Payload hash algorithm String Yes Hashing algorithm of the payload_hash. Below algorithm supported:
  • SHA-256 (RSASHA256)
  • SHA-384 (RSASHA384)
  • SHA-512 (RSASHA512)
"RSASHA256"

Example structure:

{
    "jti": "5ccfd3a0-36a1-11ea-b780-eeee0af2723c",
    "iat": 1578987726,
    "sub": "TAAS000000XXX",
    "obo": {
      "sub":"customer001"
    },
    "aud": "taas",
    "payload_hash": "a00ccb...",
    "payload_hash_alg": "RSASHA256",
}

Making an API Request

 

Return to top