Before calling any API, you must sign requests and validate response signatures to ensure message security and integrity.
Request Signing Process
Step 1: Prepare Your Private Key
Ensure your private key is ready. It must be a 2048-bit RSA key.
// Load private key from environment or secure storage
const privateKey = process.env.REBELL_PRIVATE_KEY;
// Or from file
const privateKey = fs.readFileSync('private_key.pem', 'utf-8');
from cryptography.hazmat.primitives import serialization
# Load private key
with open('private_key.pem', 'rb') as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
Step 2: Construct Content to Sign
Build a string combining the HTTP method, URI, client identifier, timestamp, and request body:
<HTTP_METHOD> <HTTP_URI>
<Client-Id>.<Request-Time>.<HTTP_BODY>
Components:
| Component | Description | Example |
|---|
| HTTP_METHOD | The HTTP method | POST |
| HTTP_URI | The API endpoint path | /api/open/v2/payments/pay |
| Client-Id | Your assigned client ID | TEST_5X00000000000000 |
| Request-Time | ISO 8601 timestamp | 2024-01-10T12:12:12+01:00 |
| HTTP_BODY | JSON request body | {"paymentRequestId":"..."} |
Example content to sign:
POST /api/open/v2/payments/pay
TEST_5X00000000000000.2024-01-10T12:12:12+01:00.{"paymentRequestId":"REQ_001","paymentAmount":{"currency":"EUR","value":"1000"}}
Step 3: Generate Signature
Apply RSA with SHA-256 algorithm to generate the signature:
const crypto = require('crypto');
function generateSignature(contentToSign, privateKey) {
const signer = crypto.createSign('RSA-SHA256');
signer.update(contentToSign);
const signature = signer.sign(privateKey, 'base64');
return signature;
}
// Build content to sign
const method = 'POST';
const uri = '/api/open/v2/payments/pay';
const clientId = 'YOUR_CLIENT_ID';
const requestTime = new Date().toISOString();
const body = JSON.stringify(requestBody);
const contentToSign = `${method} ${uri}\n${clientId}.${requestTime}.${body}`;
const signature = generateSignature(contentToSign, privateKey);
Format and add the signature header to your request:
Signature: algorithm=RSA256, keyVersion=1, signature=<generated_signature>
| Field | Description |
|---|
algorithm | Always RSA256 |
keyVersion | Your key version (provided during onboarding) |
signature | Base64-encoded signature from Step 3 |
Complete Request Example
curl -X POST https://api.rebellapp.com/api/open/v2/payments/pay \
-H 'Content-Type: application/json' \
-H 'Client-Id: TEST_5X00000000000000' \
-H 'Request-Time: 2024-01-10T12:12:12+01:00' \
-H 'Signature: algorithm=RSA256, keyVersion=1, signature=BASE64_SIGNATURE_HERE' \
-d '{
"paymentRequestId": "REQ_001",
"paymentAmount": {
"currency": "EUR",
"value": "1000"
}
}'
Response Signature Validation
Always verify the response signature before processing the data.
Construct Content to Validate
Mirror the request signing process using response data:
<HTTP_METHOD> <HTTP_URI>
<Client-Id>.<Response-Time>.<HTTP_BODY>
Verify Signature
function verifySignature(method, uri, clientId, responseTime, body, signature, publicKey) {
const contentToVerify = `${method} ${uri}\n${clientId}.${responseTime}.${body}`;
const verifier = crypto.createVerify('RSA-SHA256');
verifier.update(contentToVerify);
return verifier.verify(publicKey, signature, 'base64');
}
// Usage
const isValid = verifySignature(
'POST',
'/api/open/v2/payments/pay',
clientId,
response.headers['response-time'],
JSON.stringify(response.body),
extractSignature(response.headers['signature']),
rebellPublicKey
);
if (!isValid) {
throw new Error('Invalid response signature');
}
Key Points
Security Alert: Never log or expose the full signature content or private key. If you need to debug signature issues, log only non-sensitive parts like the method and URI.