Certain processes and workflows using Rabo Identity Services APIs contain highly sensitive PII data. To protect this data, Rabobank uses message level encryption.
Message-Level Encryption (MLE) enhances security by ensuring that sensitive data remains encrypted during transit and is implemented as an additional layer on top of standard transport layer security (TLS).
This guide explains how to provide the correct input for encryption, how encryption is performed, and how to decrypt the received content.
Follow the listed steps to use message level encryption using PKI:
Required Input
To receive an encrypted response, API clients are required to include a JSON Web Key (JWK) in the mandatory X-Encryption-Key
request header as part of any API invocation where message level encryption is applied.
Consumers of the API are responsible for generating the key(s) and storing the private part of the key securely.
Rabobank Identity Services APIs support RSA and EC key types, defined using the kty
attribute.
The minimum required key configuration is as below:
Applying RSA Keys
Field | Value | Notes |
---|---|---|
kty | RSA | Required |
alg | RSA-OAEP, RSA-OAEP-256 | Required |
use | enc | Required |
kid | Case-sensitive string identifying the key | Recommended |
e | Public exponent | Required |
n | Modulus | Required |
Applying EC Keys
Field | Value | Notes |
---|---|---|
kty | EC | Required |
alg | ECDH-ES | Required |
crv | P-256, P-384, P-521 | Required |
use | enc | Required |
kid | Case-sensitive string identifying the key | Recommended |
x | X coordinate | Required |
y | Y coordinate | Required |
Valid RSA X-Encryption-Key
Header Value
X-Encryption-Key
Header Value{
"kty": "RSA",
"e": "AQAB",
"use": "enc",
"kid": "gYtIlsCr3gGSdmY1Uj0q01ud0bDzSutAPHO9wHens4s",
"alg": "RSA-OAEP-256",
"n": "ufzviUV7l_DfVjHOegUCCAfC2jEPcHqmlbaO9ksHBGeYmpqQfp37pprcfUytVtQkvLoPOyX_0XwqrirQ4BI5ApfbxqQVuamOMd_qFzPlHqusnrbZeFIMDm0wnNM00Wezh3BQ4Jz958cqaS30mpXWec-UXfmkVOifbzjc2vcYxYY0_6-9-QTjDbpy_R7yx_FvECQO07qh7axTOwRdgNoN5mXVLs1in1Rx_QBfhcaxkTnN3R5nGaFqhiDHX2OWIfaiscv8QHqi0wpLI7du74nAmENwpFjLVHrC5D8KrD0QUN0IW8pr-wiJ8-sGmehBGDDUs6iPUNyy46Edmh8beavWKQ"
}
Setting the Header
Include the JWK (public part of the key) in the X-Encryption-Key
header in all API requests where encryption is required.
Example request:
GET /api/encrypted-resource HTTP/1.1
X-Encryption-Key: {"kty":"RSA","e":"AQAB","n":"base64url-encoded-modulus","alg":"RSA-OAEP-256","use":"enc","kid":"unique-key-id"}
Encryption Process
The API client sends a request with the X-Encryption-Key
header containing its public key:
- Rabobank validates the provided
X-Encryption-Key
. - If valid, message-level encryption is applied to the response body.
The API response payload is returned as a JWE (JSON Web Encryption) token with:
Content-Type: application/jose
You must decrypt it using a JWE-compatible library.
See: RFC7516 - JSON Web Encryption (JWE)
Decrypting the Response
To decrypt the response, use the private key corresponding to the public key sent in X-Encryption-Key
.
Example (Message-Level Encrypted Response):
HTTP/1.1 200 OK
Content-Type: application/jose
eyJraWQiOiJ1R0VIUWdBeUFfdFNBQWhhcUNRSTVJVHBrcWdhU2xCQXVhTklWQzJGRUU0IiwiZW5jIjoiQTI1NkdDTSIsImFsZyI6IlJTQS1PQUVQLTI1NiJ9...
Generic decryption logic:
FUNCTION decryptJWE(jweToken):
1. Parse the JWE token to extract encryption details.
2. Load the private key securely.
3. Use a cryptographic library to decrypt the JWE using the private key.
4. Retrieve the decrypted payload.
5. CHECK the expected content type on the API documentation:
a) IF text-based (JSON, XML) → Parse or return as text.
b) IF binary (file, image, PDF) → Handle as binary stream.
6. Return the appropriate format to the caller.
Security Considerations
- Key Rotation: Regularly update encryption keys to maintain security.
- Secure Storage: Never expose or log private keys.