Developer

Partner Docs

Merchant Docs

Field Level Encryption

Field Level Encryption (FLER) is a security feature that ensures sensitive data is protected when transmitted to and from Banked's APIs. This feature is particularly important for handling personal and financial information, providing an additional layer of security beyond standard TLS encryption.

FLER provides end-to-end encryption for sensitive data, ensuring it remains protected even when passing through third-party services.

Overview

The process involves:

  1. Choose your response protection method (redaction vs encryption)
  2. Get API credentials and share public keys with Banked
  3. Fetch Banked's public keys from the JWKS endpoint
  4. Generate RSA key pairs and manage encryption keys
  5. Encrypt sensitive data fields before sending requests
  6. Handle encrypted or redacted responses appropriately

Prerequisites:

  • Valid Banked account with API access

Implementation Steps

The implementation can be broken down into the following steps:

Step 1. Choose Response Protection Method

Before starting integration, decide how you want to handle sensitive data in responses:

MethodUse CaseSetup Required
Response RedactionFields containing sensitive data will be replaced with [REDACTED]None
Response EncryptionYou need to access sensitive data from responsesRequires RSA public key

This choice depends on your need to use the fields from the response. If you need to access the sensitive data in responses, choose response encryption.

Step 2. Get API Credentials

Contact your Banked representative to receive:

  • For Partner integrations: New OAuth credentials for generating tokens
  • For all integrations: Basic Auth credentials
  • For response encryption: Share your RSA public key

Step 3. Get Banked's Public Keys

Banked provides public keys for encryption via a JWKS (JSON Web Key Set) endpoint:

http
GET https://api.banked.com/.well-known/jwks.json

Response Format

json
{
  "keys": [
    {
      "kty": "RSA",
      "use": "enc",
      "alg": "RSA-OAEP-256",
      "kid": "1654876509",
      "n": "jbNTpPiCVdm4D-0UEcM9NkbKJk6Ro9eVfgdK8yC0IzBL2k6D6ebB_QyI5dwFiLT3ZZUp1-zQta3o...GB5R3XqD",
      "e": "AQAB",
      "bknd.exp": 1666797757,
      "bnkd.iat": 1664205757
    }
  ]
}

The n parameter contains the full RSA modulus (base64url-encoded). It's truncated here for readability, but the actual response includes the complete value.

Step 4. Generate and Manage Keys

RSA Public Key (for Response Encryption)

Skip this step if you chose response redaction in Step 1.

An RSA public key is a cryptographic key used in asymmetric encryption. It consists of two parts:

  • A public key that can be shared with others
  • A private key that must be kept secure

In the context of FLER:

  • You generate and keep the private key
  • You share the public key with Banked
  • Banked uses your public key to encrypt responses
  • You use your private key to decrypt the responses
Generating RSA Keys

Generate an RSA key pair using OpenSSL:

bash
# Generate a 2048-bit RSA private key
openssl genrsa -out private.pem 2048

# Extract the public key
openssl rsa -in private.pem -pubout -out public.pem

Keep your private key secure and never share it. If your private key is compromised, you must generate a new key pair and update your public key with Banked.

Key Requirements
  • Key size: 2048 bits minimum
  • Format: PEM
  • Algorithm: RSA
  • Public exponent: 65537 (0x10001)

Content Encryption Keys (CEK)

A Content Encryption Key is a symmetric key used to encrypt the actual data payload.

For each sensitive data object:

  1. Generate a new CEK
  2. Encrypt the CEK using Banked's public key
  3. Use the CEK to encrypt the sensitive data
  4. Never reuse CEKs between requests

Step 5. Encrypt Sensitive Data

  1. Identify fields requiring encryption (see Fields Requiring Encryption)
  2. Encrypt each sensitive field using the process above
  3. Prefix encrypted field names with encrypted_

Example Request

json
// Original
{
  "payee": {
    "name": "John Doe",
    "account_number": "12345678",
    "sort_code": "123456"
  }
}

// Encrypted
{
  "encrypted_payee": "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiMTY1NDg3NjUwOSJ9..."
}

Step 6. Handle Responses

Redacted Response

json
{
  "payee": {
    "name": "[REDACTED]",
    "account_number": "[REDACTED]",
    "sort_code": "[REDACTED]"
  }
}

Encrypted Response

  • Content-Type: application/jose
  • Format: JWE (JSON Web Encryption)
  • Algorithm: RSA-OAEP-256
  • Encoding: A256GCM

API Reference

Fields Requiring Encryption

Payment Sessions API

EndpointFieldSensitivityRequestResponse
POST /v2/payment_sessionspayeehighencryptredact/encrypt
POST /v2/payment_sessionspayerhighencryptredact/encrypt
POST /v2/payment_sessionsmandate_idhighencryptencrypt
POST /v2/payment_sessionsmandatehighencryptredact/encrypt
GET /v2/payment_sessionspayeehighN/Aredact/encrypt
GET /v2/payment_sessionspayerhighN/Aredact/encrypt

Bank Accounts API

EndpointFieldSensitivityRequestResponse
POST /v2/bank_accountsnamelowencryptredact
POST /v2/bank_accountsaccount_identifierhighencryptredact
POST /v2/bank_accountssort_codehighencryptredact
POST /v2/bank_accountsaccount_numberhighencryptredact
POST /v2/bank_accountssecondary_identifierhighencryptredact

Mandates API

EndpointFieldSensitivityRequestResponse
POST /v2/mandatessourcehighencryptredact
POST /v2/mandatesdestinationhighencryptredact
POST /v2/mandatesactions.#.sourcehighencryptredact

Error Responses

Invalid Encryption Key

http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
    "errors": [
        {
            "code": "invalid",
            "source": "encryption key",
            "title": "invalid encryption key"
        }
    ]
}

When receiving this error, fetch a new key from the JWKS endpoint, re-encrypt your payload, and submit a new request.

Code Examples

Go Implementation

go
package main

import (
    "crypto/rsa"
    "fmt"
    "log"

    "github.com/lestrrat/go-jwx/jwk"
    "gopkg.in/square/go-jose.v2"
)

// Get Banked's public key
func GetJWK() (jwk.Key, *rsa.PublicKey, error) {
    set, err := jwk.Fetch("https://api.banked.com/.well-known/jwks.json")
    if err != nil {
        return nil, nil, err
    }

    key := set.Keys[0]
    r, err := key.Materialize()
    if err != nil {
        return nil, nil, err
    }

    rk, ok := r.(*rsa.PublicKey)
    if !ok {
        return nil, nil, fmt.Errorf("not an RSA Public Key")
    }

    return key, rk, nil
}

// Encrypt sensitive data
func Encrypt(b []byte) ([]byte, error) {
    k, r, err := GetJWK()
    if err != nil {
        return nil, err
    }

    encrypter, err := jose.NewEncrypter(
        jose.A256GCM,
        jose.Recipient{
            Algorithm: jose.RSA_OAEP_256,
            Key: r,
            KeyID: k.KeyID(),
        },
        nil,
    )
    if err != nil {
        return nil, err
    }

    encrypted, err := encrypter.Encrypt(b)
    if err != nil {
        return nil, err
    }

    return []byte(encrypted.CompactSerialize()), nil
}

Best Practices

  1. Generate new CEK for each sensitive data object
  2. Do not reuse CEKs between requests
  3. Cache public keys and refresh before expiry
  4. Handle key rotation gracefully
  5. Implement proper error handling for encryption/decryption failures

© 2025 Banked Ltd.

Dark Theme
PrivacyTerms