Skip to content

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

  1. Read the X-Signature header from the request.
  2. Compute HMAC_SHA256(secret_key, raw_request_body).
  3. 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')