To ensure secure communication with the Rumbapay API, all requests must include a signature in the headers. Similarly, all responses from the Rumbapay API will contain a signature header as well. This signature verifies the authenticity of both requests and responses, ensuring the integrity of the payload in both directions.
Signature Formula:
signature = HMACSHA256(Password, Login + JSON)
Where:
Login: Your merchant login
JSON: The complete JSON request/response body as a string
Password: Your merchant password (used as the secret key for HMAC)
Note: The signature must be included in the headers of every API request, and Rumbapay will always include a signature header in all responses. Validating this signature in responses is essential to ensure the response hasn't been tampered with during transmission.
Security Note: HMACSHA256 provides improved security over standard SHA256 by using a secret key (your password) in the hashing process, which helps protect against certain types of cryptographic attacks.
Signature Implementation Examples
1. Node.js Example
const crypto = require('crypto');
function generateSignature(login, jsonData, password) {
// Convert JSON to string if it's an object
const jsonString = typeof jsonData === 'object' ? JSON.stringify(jsonData) : jsonData;
// Concatenate login + JSON
const dataToSign = login + jsonString;
// Generate HMACSHA256 hash using password as the key
return crypto.createHmac('sha256', password).update(dataToSign).digest('hex');
}
// Example usage
const login = 'john_yablonliy';
const password = '4f56cc8f-eb99-4b5d-9255-52ae6f23e91c';
const jsonData = { /* Your JSON data */ };
const signature = generateSignature(login, jsonData, password);
console.log('Signature:', signature);
// Add signature to request headers
const headers = {
'Content-Type': 'application/json',
'signature': signature
};
2. C# Example
using System;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
public class SignatureGenerator
{
public static string GenerateSignature(string login, object jsonData, string password)
{
// Convert JSON to string if it's an object
string jsonString = jsonData is string ? (string)jsonData : JsonConvert.SerializeObject(jsonData);
// Concatenate login + JSON
string dataToSign = login + jsonString;
// Generate HMACSHA256 hash using password as the key
using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password)))
{
byte[] bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(dataToSign));
// Convert to hex string
StringBuilder builder = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
builder.Append(bytes[i].ToString("x2"));
}
return builder.ToString();
}
}
// Example usage
public static void Main()
{
string login = "john_yablonliy";
string password = "4f56cc8f-eb99-4b5d-9255-52ae6f23e91c";
var jsonData = new { /* Your JSON data */ };
string signature = GenerateSignature(login, jsonData, password);
Console.WriteLine("Signature: " + signature);
// Add signature to request headers
// httpClient.DefaultRequestHeaders.Add("signature", signature);
}
}
3. Java Example
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.fasterxml.jackson.databind.ObjectMapper;
public class SignatureGenerator {
public static String generateSignature(String login, Object jsonData, String password) throws Exception {
// Convert JSON to string if it's an object
String jsonString;
if (jsonData instanceof String) {
jsonString = (String) jsonData;
} else {
ObjectMapper mapper = new ObjectMapper();
jsonString = mapper.writeValueAsString(jsonData);
}
// Concatenate login + JSON
String dataToSign = login + jsonString;
// Generate HMACSHA256 hash using password as the key
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(password.getBytes("UTF-8"), "HmacSHA256");
hmacSha256.init(secretKey);
byte[] hash = hmacSha256.doFinal(dataToSign.getBytes("UTF-8"));
// Convert to hex string
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
// Example usage
public static void main(String[] args) {
try {
String login = "john_yablonliy";
String password = "4f56cc8f-eb99-4b5d-9255-52ae6f23e91c";
Object jsonData = /* Your JSON data */;
String signature = generateSignature(login, jsonData, password);
System.out.println("Signature: " + signature);
// Add signature to request headers
// connection.setRequestProperty("signature", signature);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Security Best Practices
Always use HTTPS for all API communications.
Keep your login and password secure; never expose them in client-side code.
Validate both request and response signatures to ensure data integrity.
Use proper error handling for failed signature validations.
Implement request timeouts to prevent replay attacks.
Using HMACSHA256 over standard SHA256 provides better security as it includes a secret key in the hashing process.
Validating Responses
To validate API responses, follow a similar process:
Extract the signature from the response headers.
Generate a signature using the HMACSHA256 algorithm with your password as the key and login + response body as the message.
Compare the generated signature with the received signature.
If they match, the response is authentic and hasn't been tampered with.
// Example validation pseudo-code
const receivedSignature = response.headers.get('signature');
const calculatedSignature = generateSignature(login, response.body, password);
if (receivedSignature === calculatedSignature) {
// Response is valid, proceed with processing
} else {
// Signature mismatch, possible tampering or transmission error
throw new Error('Invalid response signature');
}