Encryption & Decryption
This guide explains how to encrypt responses and decrypt incoming webhook requests using AES-256-ECB encryption.
Encryption Specification
Section titled “Encryption Specification”- Algorithm: AES (Advanced Encryption Standard)
- Key Size: 256 bits
- Mode: ECB (Electronic Codebook)
- Padding: PKCS#7 (also known as PKCS5)
- Encryption Key: Your API Key
Request Flow (Decryption)
Section titled “Request Flow (Decryption)”When you receive a webhook request, follow this flow:
Decryption Example
Section titled “Decryption Example”import crypto from 'crypto';
function decrypt(encryptedData, apiKey) { // Create decipher with AES-256-ECB const decipher = crypto.createDecipheriv( 'aes-256-ecb', Buffer.from(apiKey, 'utf8'), null // ECB mode doesn't use IV );
// Disable automatic padding decipher.setAutoPadding(true);
// Decrypt the data let decrypted = decipher.update(encryptedData, 'base64', 'utf8'); decrypted += decipher.final('utf8');
return JSON.parse(decrypted);}
// Usageapp.post('/webhook', express.text(), (req, res) => { const encryptedBody = req.body; const decryptedData = decrypt(encryptedBody, API_KEY);
console.log(decryptedData); /* { "transaction_id": "2_sandboxagent01_1763107598923_1922", "event_type": "bet", "timestamp": 1763107599, "feedback_data": "TEST_FEEDBACK_DATA", "user_id": "edwincalma", "data": { "currency": "KRW", "game_type": "BAC", "table_no": "DH002", "game_no": "DH0022511141328", "total_bet_amount": 5000, "bets": [ { "bet_index": "10404", "bet_type": "P", "bet_amount": 5000 } ] } } */});Response Flow (Encryption)
Section titled “Response Flow (Encryption)”When sending a response, follow this flow:
Encryption Example
Section titled “Encryption Example”function encrypt(data, apiKey) { // Create cipher with AES-256-ECB const cipher = crypto.createCipheriv( 'aes-256-ecb', Buffer.from(apiKey, 'utf8'), null // ECB mode doesn't use IV );
// Enable automatic padding cipher.setAutoPadding(true);
// Convert data to JSON string const jsonString = JSON.stringify(data);
// Encrypt the data let encrypted = cipher.update(jsonString, 'utf8', 'base64'); encrypted += cipher.final('base64');
return encrypted;}
// Usageconst responseData = { result_code: 0, response_data: { balance: 10000 }};
const encryptedResponse = encrypt(responseData, API_KEY);res.status(200).send(encryptedResponse);Complete Webhook Handler
Section titled “Complete Webhook Handler”Here’s a complete example combining both decryption and encryption:
import express from 'express';import crypto from 'crypto';
const app = express();const API_KEY = 'your-32-character-api-key-here';
// Helper functionsfunction decrypt(encryptedData, apiKey) { const decipher = crypto.createDecipheriv( 'aes-256-ecb', Buffer.from(apiKey, 'utf8'), null ); decipher.setAutoPadding(true); let decrypted = decipher.update(encryptedData, 'base64', 'utf8'); decrypted += decipher.final('utf8'); return JSON.parse(decrypted);}
function encrypt(data, apiKey) { const cipher = crypto.createCipheriv( 'aes-256-ecb', Buffer.from(apiKey, 'utf8'), null ); cipher.setAutoPadding(true); const jsonString = JSON.stringify(data); let encrypted = cipher.update(jsonString, 'utf8', 'base64'); encrypted += cipher.final('base64'); return encrypted;}
// Webhook endpointapp.post('/webhook', express.text(), (req, res) => { try { // Decrypt incoming request const payload = decrypt(req.body, API_KEY); console.log('Received:', payload);
// Process based on command type let responseData;
switch (payload.command) { case 'login': // Validate user and return balance responseData = { "code": "R0", // Required, String "event_type": "login", // Required, String "timestamp": 1763107693, // Required, Number "user_id": "edwincalma", // Required, String "latest_balance": 1111000 // Required, Number }; break;
case 'bet': // Deduct bet amount const betAmount = payload.data.bet_gold; responseData = { "code": "R0", // Required, String "event_type": "bet", // Required, String "timestamp": 1763107509, // Required, Number "user_id": "edwincalma", // Required, String "latest_balance": 1000000 // REQUIRED, Number }; break;
// Handle other commands... }
// Encrypt and send response const encryptedResponse = encrypt(responseData, API_KEY); res.status(200).send(encryptedResponse);
} catch (error) { console.error('Error processing webhook:', error);
// Even on error, send encrypted response const errorResponse = { result_code: 1, response_data: { message: 'Internal server error' } }; const encryptedError = encrypt(errorResponse, API_KEY); res.status(200).send(encryptedError); }});
app.listen(3000, () => { console.log('Webhook server running on port 3000');});Important Notes
Section titled “Important Notes”Common Issues
Section titled “Common Issues”Issue: Padding Error
Section titled “Issue: Padding Error”Solution: Ensure setAutoPadding(true) is called on both cipher and decipher.
Issue: Invalid Key Length
Section titled “Issue: Invalid Key Length”Solution: Verify your API Key is exactly 32 characters.
Issue: Cannot Parse JSON
Section titled “Issue: Cannot Parse JSON”Solution: Check that you’re using the correct encoding (base64 for encrypted, utf8 for decrypted).
Next Steps
Section titled “Next Steps”- Implement webhook handlers for each Seamless Event