Overview
FinProServer supports end-to-end encryption on API payloads. When enabled, request bodies must be encrypted before sending, and responses are returned encrypted — protecting sensitive financial data in transit. The encryption scheme uses two layers working together: a symmetric cipher (AES-256-GCM) to encrypt the payload efficiently, and an asymmetric cipher (RSA-OAEP) to securely exchange the symmetric key with the server. The encrypted key bundle sent in each request is called the KEK (Key Encryption Key) — a fresh one is generated per request.Encryption Architecture
Two layers work together on every request:Layer 1 — RSA (Key Exchange)
- Algorithm: RSA-OAEP (SHA-1 hash, 2048/4096-bit key)
- Encrypts:
"key:iv"UTF-8 string - Sent in: Request Header →
kek
Layer 2 — AES (Payload Encryption)
- Algorithm: AES-256-GCM
- Key: 32 bytes · IV: 12 bytes
- Encrypts: JSON request body
- Sent in: Request Body →
RequestEncryptedValue
Step-by-Step Encryption Process
Perform these 8 steps for every API request:1
Prepare Your JSON Payload
Serialize your request data to a valid JSON string with UTF-8 encoding.
2
Generate Random AES Key
Generate a cryptographically secure random key:
- Length: 32 bytes (256 bits)
- Format: Printable ASCII characters recommended (alphanumeric, no colon)
- Generate fresh for every request
3
Generate Random IV
Generate a cryptographically secure random IV:
- Length: 12 bytes (96 bits) — required for AES-GCM
- Format: Printable ASCII characters (alphanumeric, no colon)
- Must be unique per request
4
Encrypt Payload with AES-256-GCM
Encrypt your JSON string:Process:
- Encrypt JSON with AES-256-GCM → produces ciphertext + 16-byte auth tag
- Base64-encode ciphertext:
ct_b64 = base64(ciphertext) - Base64-encode auth tag:
tag_b64 = base64(auth_tag)— always 24 characters - Concatenate:
encrypted_payload = ct_b64 + tag_b64
5
Combine Key + IV
Create a single plain UTF-8 string with key and IV separated by a colon:32 ASCII chars +
: + 12 ASCII chars = 45 characters total.6
RSA-OAEP Encrypt the Key:IV String (Create KEK)
7
Base64 Encode the KEK
b85X0Yg0aaWRX969R/51SyUkOBiKCVPk5SmFVmhb+eLBgb4e6OH0UE4RxZia...8
Build and Send the HTTP Request
Headers:
Body:
Request Format
Complete Example
Header Reference
Body Reference
Response Decryption
The server responds with an encrypted payload in the same format:Decryption Flow
1
Split the payload
Extract the last 24 characters →
base64(auth_tag). Everything before = base64(ciphertext).2
Base64-decode both parts
3
Decrypt with AES-256-GCM
Use the same Key and IV from your original request. GCM verifies the auth tag automatically.
4
Parse JSON
The decrypted bytes are the original plaintext JSON response.
Key points for response decryption:
- Reuse the same Key and IV you generated for the request — store them after Steps 2 & 3
- The response format is identical to the request:
base64(ciphertext) + base64(auth_tag)— no IV in the payload - Auth tag is always the last 24 characters (base64-encoded 16-byte GCM tag)
Prerequisites
Application Registration
Contact FinProServer administrators to register your application. You will receive:
Client-side capabilities required:
- Generate cryptographically secure random bytes (for AES key and IV)
- AES-256-GCM encryption and decryption
- RSA-OAEP encryption (asymmetric)
- Base64 encoding and decoding
- HTTP requests with custom headers
Algorithm Summary
Encryption Flow Summary
Code Examples
Troubleshooting
Debug Checklist:- Server RSA public key is correct and in PEM format
- Application identifier is registered and matches exactly
- AES key is exactly 32 bytes (256 bits)
- IV is exactly 12 bytes (96 bits) — GCM requires 12-byte IV
- New random Key and IV are generated for every request
- Request payload is valid JSON before encryption
- Encrypted payload format:
base64(ciphertext) + base64(auth_tag)— NO IV prepended in body - KEK input is plain UTF-8
"key:iv"string — NOT Base64-encoded before RSA - RSA padding is OAEP with SHA-1 (not PKCS1 v1.5, not SHA-256)
- RSA-encrypted KEK bytes are Base64-encoded before putting in
kekheader - Both
kekandappIdentifierheaders are present on every request - Request body contains only the
RequestEncryptedValuefield - Same Key and IV are used to decrypt the response
- Response: last 24 chars =
base64(auth_tag); remaining =base64(ciphertext) - Auth tag is passed into GCM decrypt — not stripped from the payload first
oaep decoding error
oaep decoding error
Likely cause: Wrong RSA public key, or
key:iv was Base64-encoded before RSA encryption.Fix: Use the correct server public key. Pass the raw UTF-8 bytes of "key:iv" directly to RSA encrypt — do not Base64-encode first.GCM auth tag mismatch
GCM auth tag mismatch
Likely cause: Wrong key/IV used for decryption, or IV was prepended to the payload body.Fix: Do not prepend the IV to the payload — it lives only in the
kek header. Use the exact same key + IV from your original request to decrypt the response.AES key invalid size
AES key invalid size
Likely cause: Key is not exactly 32 bytes.Fix: Generate exactly 32 alphanumeric ASCII characters (32 UTF-8 bytes = 256 bits).
Decryption returns garbage
Decryption returns garbage
Likely cause: Payload parts split incorrectly.Fix: Ensure last 24 chars →
auth_tag; all remaining chars → ciphertext. Base64-decode each part separately before passing to GCM.