Encryption
Two Omniware APIs offer an encrypted variant where the request body is AES-256-encrypted before posting:
| API | Algorithm | Notes |
|---|---|---|
| Encrypted Payment Request | AES-256-CBC | Random 16-byte IV, base64-encoded with the ciphertext. |
| Register Merchant | AES-256-ECB | No IV. ECB is acceptable here only because every request body has unique content (PAN, contact details). |
In both cases the api_key stays in plaintext alongside the encrypted blob so Omniware knows which encryption key to use to decrypt.
AES-256-CBC (Payment Request)
The plaintext is a JSON-serialised version of the normal Payment Request parameters (see Encrypted Payment Request for the exact shape).
- PHP
- Node.js
- Python
- Java
function encryptData(string $plain_data, string $encryption_key): array
{
$iv = openssl_random_pseudo_bytes(16);
$encrypted = openssl_encrypt(
$plain_data,
'AES-256-CBC',
$encryption_key,
OPENSSL_RAW_DATA,
$iv
);
return [base64_encode($encrypted), base64_encode($iv)];
}
function decryptData(string $encrypted_data, string $decryption_key, string $iv): string
{
return openssl_decrypt(
base64_decode($encrypted_data),
'AES-256-CBC',
$decryption_key,
OPENSSL_RAW_DATA,
base64_decode($iv)
);
}
import crypto from "node:crypto";
export function encrypt(plain, key) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv("aes-256-cbc", Buffer.from(key), iv);
const encrypted = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
return {
encrypted_data: encrypted.toString("base64"),
iv: iv.toString("base64"),
};
}
export function decrypt(encryptedB64, key, ivB64) {
const decipher = crypto.createDecipheriv(
"aes-256-cbc",
Buffer.from(key),
Buffer.from(ivB64, "base64")
);
const decrypted = Buffer.concat([
decipher.update(Buffer.from(encryptedB64, "base64")),
decipher.final(),
]);
return decrypted.toString("utf8");
}
import base64, os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
def encrypt(plain: str, key: str) -> dict:
iv = os.urandom(16)
cipher = AES.new(key.encode(), AES.MODE_CBC, iv)
ct = cipher.encrypt(pad(plain.encode(), AES.block_size))
return {
"encrypted_data": base64.b64encode(ct).decode(),
"iv": base64.b64encode(iv).decode(),
}
def decrypt(encrypted_b64: str, key: str, iv_b64: str) -> str:
cipher = AES.new(key.encode(), AES.MODE_CBC, base64.b64decode(iv_b64))
return unpad(cipher.decrypt(base64.b64decode(encrypted_b64)), AES.block_size).decode()
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;
public static String[] encrypt(String plain, String key) throws Exception {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(), "AES"), new IvParameterSpec(iv));
byte[] ct = c.doFinal(plain.getBytes("UTF-8"));
return new String[] {
Base64.getEncoder().encodeToString(ct),
Base64.getEncoder().encodeToString(iv),
};
}
public static String decrypt(String encryptedB64, String key, String ivB64) throws Exception {
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE,
new SecretKeySpec(key.getBytes(), "AES"),
new IvParameterSpec(Base64.getDecoder().decode(ivB64)));
return new String(c.doFinal(Base64.getDecoder().decode(encryptedB64)), "UTF-8");
}
The post body has three fields: api_key, encrypted_data, and iv. The response on return_url follows the same shape — decrypt encrypted_data with your decryption_key and the iv Omniware returns.
AES-256-ECB (Register Merchant)
Used only for the Register Merchant endpoint. ECB requires no IV but has a known weakness for repeated plaintext blocks — it is acceptable here because merchant registration payloads always contain unique identifying fields.
- PHP
- Node.js
- Python
function encryptECB(string $plain, string $key): string {
return base64_encode(openssl_encrypt($plain, 'AES-256-ECB', $key, OPENSSL_RAW_DATA));
}
import crypto from "node:crypto";
export function encryptECB(plain, key) {
const cipher = crypto.createCipheriv("aes-256-ecb", Buffer.from(key), null);
const encrypted = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
return encrypted.toString("base64");
}
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
def encrypt_ecb(plain: str, key: str) -> str:
cipher = AES.new(key.encode(), AES.MODE_ECB)
return base64.b64encode(cipher.encrypt(pad(plain.encode(), AES.block_size))).decode()
Key handling rules
encryption_keyanddecryption_keyare server-side secrets. Never embed in browser JS, mobile binaries, or public repos.- Treat the random IV as ciphertext, not a secret — but never reuse an IV across two CBC requests with the same key.
- Rotate keys via your Omniware relationship manager if you suspect compromise.