Authentication & Security
Security is critical for wallet integrations. Flex-Soft employs a dual-layer security model.
1. Signature Validation (HMAC SHA256)
All requests from Flex-Soft to your Wallet API are signed using HMAC SHA-256.
- Header:
X-Signature - Algorithm: HMAC-SHA256
- Secret: Shared secret key provided during onboarding.
- Payload: The raw JSON request body.
How to Validate
- Read the
X-Signatureheader from the request. - Compute
HMAC_SHA256(secret_key, raw_request_body). - Compare your computed hash with the header value.
[!WARNING] If the signatures do not match, you must reject the request with HTTP 401.
2. IP Whitelisting
For additional security, we recommend whitelisting Flex-Soft's server IP addresses.
- 185.xxx.xxx.xxx
- 185.yyy.yyy.yyy
(Contact support for the full list of production IPs).
3. Code Samples (Generation & Validation)
Wallet API: You must validate the signature (Inbound). Gift API: You must generate a signature (Outbound).
Below are examples of how to do both.
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class SignatureHelper {
// Use this to VALIDATE requests from Flex-Soft (Wallet API)
public static boolean isValid(String secretKey, String rawBody, String headerSignature) {
String computed = sign(secretKey, rawBody);
return computed.equals(headerSignature);
}
// Use this to GENERATE signatures for requests to Flex-Soft (Gift API)
public static String sign(String secretKey, String message) {
try {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(
secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
mac.init(secretKeySpec);
byte[] rawHmac = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(rawHmac);
} catch (Exception e) {
throw new RuntimeException("Failed to calculate HMAC", e);
}
}
}
using System;
using System.Security.Cryptography;
using System.Text;
public class SignatureHelper {
// Use this to VALIDATE requests from Flex-Soft (Wallet API)
public static bool IsValid(string secretKey, string rawBody, string headerSignature) {
string computed = Sign(secretKey, rawBody);
return computed == headerSignature;
}
// Use this to GENERATE signatures for requests to Flex-Soft (Gift API)
public static string Sign(string secretKey, string message) {
var encoding = new UTF8Encoding();
byte[] keyBytes = encoding.GetBytes(secretKey);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmac = new HMACSHA256(keyBytes)) {
byte[] hashMessage = hmac.ComputeHash(messageBytes);
return Convert.ToBase64String(hashMessage);
}
}
}
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
)
// Use this to VALIDATE requests from Flex-Soft (Wallet API)
func IsValid(secretKey, rawBody, headerSignature string) bool {
computed := Sign(secretKey, rawBody)
return computed == headerSignature
}
// Use this to GENERATE signatures for requests to Flex-Soft (Gift API)
func Sign(secretKey, message string) string {
key := []byte(secretKey)
h := hmac.New(sha256.New, key)
h.Write([]byte(message))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
import hmac
import hashlib
import base64
# Use this to VALIDATE requests from Flex-Soft (Wallet API)
def is_valid(secret_key, raw_body, header_signature):
computed = sign(secret_key, raw_body)
return computed == header_signature
# Use this to GENERATE signatures for requests to Flex-Soft (Gift API)
def sign(secret_key, message):
key = bytes(secret_key, 'utf-8')
msg = bytes(message, 'utf-8')
raw_hmac = hmac.new(key, msg, hashlib.sha256).digest()
return base64.b64encode(raw_hmac).decode('utf-8')