Example Walkthrough
Complete step-by-step example of integrating 4Quays into a banking application
This walkthrough demonstrates integrating 4Quays into a banking application that sends transfers to multiple banks with different cryptographic requirements.
Scenario
Your application needs to integrate with three financial institutions:
| Service | Requirement |
|---|---|
| Bank A | AES-256-GCM encryption with RSA key wrapping |
| Bank B | AES-256-GCM encryption with ML-KEM-768 (post-quantum) |
| Bank C | Plaintext over TLS only |
Before 4Quays
Your current code might look like this:
// banking-service.js (before 4Quays)
import { loadKey, encryptWithRSA, encryptWithMLKEM } from './crypto';
async function sendTransfer(accountId, transferData) {
const account = await getAccount(accountId);
if (account.bank === 'bank-a') {
const key = loadKey('bank-a-public.pem');
const encrypted = encryptWithRSA(transferData, key);
return await bankAApi.submitTransfer(encrypted);
}
if (account.bank === 'bank-b') {
const key = loadKey('bank-b-pqc-public.pem');
const encrypted = encryptWithMLKEM(transferData, key);
return await bankBApi.submitTransfer(encrypted);
}
if (account.bank === 'bank-c') {
// Plaintext over TLS
return await bankCApi.submitTransfer(transferData);
}
}
Problems with this approach:
- Crypto logic embedded in application code
- Key management scattered across files
- Each algorithm change requires code changes
- No centralized audit trail
- Developers must understand cryptographic details
Step 1: Platform Setup
In the 4Quays dashboard:
Register Services
Your Application (source service)
- Name: "Banking Service"
- Type: Source
Bank A (destination service)
- Name: "Bank A"
- Type: Destination
- Import their RSA public key
Bank B (destination service)
- Name: "Bank B"
- Type: Destination
- Import their ML-KEM public key
Create Policies
Bank A Transfer Policy
- Policy Number:
BANK-A-TRANSFER - Algorithm: AES-256-GCM + RSA-2048
- Source: Banking Service
- Destination: Bank A
- Policy Number:
Bank B Transfer Policy
- Policy Number:
BANK-B-TRANSFER - Algorithm: AES-256-GCM + ML-KEM-768
- Source: Banking Service
- Destination: Bank B
- Policy Number:
Generate API Key
Create an API key for your application. Store it securely.
Step 2: Install SDK
npm install @4quays/sdk
Step 3: Initialize SDK
// lib/fourq.js
import { FourQ } from '@4quays/sdk';
export const fourq = new FourQ({
endpoint: process.env.FOURQ_ENDPOINT,
apiKey: process.env.FOURQ_API_KEY,
});
Step 4: Create Policy Mapping
// config/policies.js
export const bankPolicies = {
'bank-a': 'BANK-A-TRANSFER',
'bank-b': 'BANK-B-TRANSFER',
'bank-c': null, // No policy = plaintext over TLS
};
Step 5: Update Transfer Logic
// banking-service.js (with 4Quays)
import { fourq } from './lib/fourq';
import { bankPolicies } from './config/policies';
async function sendTransfer(accountId, transferData) {
const account = await getAccount(accountId);
const policy = bankPolicies[account.bank];
// Build the transfer payload
const payload = {
transferId: generateId(),
sourceAccount: account.number,
destinationIban: transferData.destination,
amount: transferData.amount,
currency: 'CAD',
memo: transferData.memo,
};
// Protect if policy exists, otherwise send plaintext
const protectedPayload = policy
? await fourq.protect(payload, policy)
: payload;
// Get the appropriate bank API
const bankApi = getBankApi(account.bank);
// Send to bank - same code for all banks
return await bankApi.submitTransfer({
encryption: protectedPayload,
timestamp: new Date().toISOString(),
});
}
Step 6: Handle Responses
If banks return encrypted responses:
async function getStatement(accountId) {
const account = await getAccount(accountId);
const bankApi = getBankApi(account.bank);
const response = await bankApi.getStatement(account.number);
// Unprotect if encrypted
const policy = bankPolicies[account.bank];
if (policy && response.encryption) {
return await fourq.unprotect(response.encryption, policy);
}
return response.data;
}
What Changed
| Before | After |
|---|---|
| Multiple crypto libraries imported | Single SDK import |
| Key files in application | Keys in 4Quays platform |
| Algorithm logic in code | Algorithm in policy |
| Per-bank crypto code | Single protect() call |
| No audit trail | Full audit in 4Quays |
The Resulting Code
The complete updated service:
// banking-service.js
import { fourq } from './lib/fourq';
import { bankPolicies } from './config/policies';
export async function sendTransfer(accountId, transferData) {
const account = await getAccount(accountId);
const policy = bankPolicies[account.bank];
const payload = {
transferId: generateId(),
sourceAccount: account.number,
destinationIban: transferData.destination,
amount: transferData.amount,
currency: 'CAD',
memo: transferData.memo,
};
const protectedPayload = policy
? await fourq.protect(payload, policy)
: payload;
const bankApi = getBankApi(account.bank);
return await bankApi.submitTransfer({
encryption: protectedPayload,
timestamp: new Date().toISOString(),
});
}
export async function getStatement(accountId) {
const account = await getAccount(accountId);
const bankApi = getBankApi(account.bank);
const response = await bankApi.getStatement(account.number);
const policy = bankPolicies[account.bank];
if (policy && response.encryption) {
return await fourq.unprotect(response.encryption, policy);
}
return response.data;
}
Algorithm Migration Example
When Bank A announces they're migrating to post-quantum:
Before 4Quays: Developers update crypto code, test, deploy.
With 4Quays:
- Security team updates the BANK-A-TRANSFER policy
- Changes algorithm from RSA to ML-KEM-768
- Policy version is incremented automatically
- Next
protect()call uses new algorithm - No code changes required
Development Testing
During development without 4Quays running:
# .env.development # FOURQ_ENDPOINT= (not set)
The code works the same, but Bank A and B receive plaintext (and may reject). This is expected — you're testing business logic, not crypto.
Production Deployment
For production:
# .env.production FOURQ_ENDPOINT=https://api.4quays.com FOURQ_API_KEY=sk_live_xxxxx
Same code, different config. Bank A and B now receive properly encrypted payloads.
What's Next
- Platform Guide — Learn to manage services and policies
- API Reference — Detailed API documentation
- Security Best Practices — Security recommendations