← Back to Documentation
🔐

Response Generation Guide

Response Generation Guide

Overview

When you receive a challenge from the API, you need to generate a response that can be validated. The current implementation accepts any response initially (for flexibility), but you should implement a secure response generation method for production use.

Response Generation Methods

Method 1: Echo (Testing Only)

The simplest method - just return the challenge as-is. Only use this for testing!

All Languages:

javascript
// Node.js
function generateResponse(challenge) {
  return challenge;
}
java
// Java
public String generateResponse(String challenge) {
    return challenge;
}
kotlin
// Kotlin
fun generateResponse(challenge: String): String = challenge
csharp
// C#
public string GenerateResponse(string challenge) {
    return challenge;
}
go
// Go
func GenerateResponse(challenge string) string {
    return challenge
}

Method 2: HMAC-SHA256 (Recommended for Production)

Generate an HMAC-SHA256 hash of the challenge using a secret key. This is the most secure method.

Node.js:

javascript
const crypto = require('crypto');

function generateResponse(challenge, secret) {
  return crypto.createHmac('sha256', secret)
    .update(challenge)
    .digest('hex');
}

Java:

java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

public String generateResponse(String challenge, String secret) throws Exception {
    Mac mac = Mac.getInstance("HmacSHA256");
    SecretKeySpec secretKeySpec = new SecretKeySpec(
        secret.getBytes(StandardCharsets.UTF_8),
        "HmacSHA256"
    );
    mac.init(secretKeySpec);
    byte[] hash = mac.doFinal(challenge.getBytes(StandardCharsets.UTF_8));
    
    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();
}

Kotlin:

kotlin
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

fun generateResponse(challenge: String, secret: String): String {
    val mac = Mac.getInstance("HmacSHA256")
    val secretKeySpec = SecretKeySpec(
        secret.toByteArray(Charsets.UTF_8),
        "HmacSHA256"
    )
    mac.init(secretKeySpec)
    val hash = mac.doFinal(challenge.toByteArray(Charsets.UTF_8))
    return hash.joinToString("") { "%02x".format(it) }
}

C#:

csharp
using System.Security.Cryptography;
using System.Text;

public string GenerateResponse(string challenge, string secret) {
    using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret))) {
        var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(challenge));
        return BitConverter.ToString(hash).Replace("-", "").ToLower();
    }
}

Go:

go
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
)

func GenerateResponse(challenge, secret string) string {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write([]byte(challenge))
    return hex.EncodeToString(mac.Sum(nil))
}

Method 3: SHA256 Hash

Generate a SHA256 hash of the challenge combined with a secret.

Node.js:

javascript
const crypto = require('crypto');

function generateResponse(challenge, secret) {
  return crypto.createHash('sha256')
    .update(challenge + secret)
    .digest('hex');
}

Java:

java
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;

public String generateResponse(String challenge, String secret) throws Exception {
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    byte[] hash = digest.digest((challenge + secret).getBytes(StandardCharsets.UTF_8));
    
    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();
}

Kotlin:

kotlin
import java.security.MessageDigest

fun generateResponse(challenge: String, secret: String): String {
    val digest = MessageDigest.getInstance("SHA-256")
    val hash = digest.digest((challenge + secret).toByteArray(Charsets.UTF_8))
    return hash.joinToString("") { "%02x".format(it) }
}

C#:

csharp
using System.Security.Cryptography;
using System.Text;

public string GenerateResponse(string challenge, string secret) {
    using (var sha256 = SHA256.Create()) {
        var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(challenge + secret));
        return BitConverter.ToString(hash).Replace("-", "").ToLower();
    }
}

Go:

go
import (
    "crypto/sha256"
    "encoding/hex"
)

func GenerateResponse(challenge, secret string) string {
    hash := sha256.Sum256([]byte(challenge + secret))
    return hex.EncodeToString(hash[:])
}

Complete Flow Example

http
   POST /api/challenge/create
   {
     "key": "kc_your_api_key",
     "ttl": 30
   }
  • Create Challenge:
javascript
   const challenge = "abc123..."; // from step 1
   const secret = "your-secret-key";
   const response = generateHMAC(challenge, secret);
  • Generate Response (using HMAC-SHA256):
http
   POST /api/challenge/validate
   {
     "key": "kc_your_api_key",
     "challenge": "abc123...",
     "response": "generated_response_hex"
   }
  • Validate:

Important Notes

  • For Testing: Use the echo method or get a free sandbox key from /playground
  • For Production: Always use HMAC-SHA256 with a secure secret
  • Secret Management: Never commit secrets to version control. Use environment variables or secret management services.
  • Response Format: Responses should be hexadecimal strings (lowercase recommended)

Security Best Practices

  • Use a strong, randomly generated secret (at least 32 bytes)
  • Store secrets securely (environment variables, secret managers)
  • Use HMAC-SHA256 for production applications
  • Never log or expose your secret key
  • Rotate secrets periodically