const crypto = require('crypto');
// Simulated API request
function createApiRequest(apiKey, secretKey, method, path, queryParams, body, timestamp) {
// Create the string to sign
const stringToSign = [
method.toUpperCase(),
path,
new URLSearchParams(queryParams).toString(),
typeof body === 'string' ? body : JSON.stringify(body || {}),
timestamp
].join('\n');
// Create HMAC signature
const hmac = crypto.createHmac('sha256', secretKey);
hmac.update(stringToSign);
const signature = hmac.digest('hex');
// Return the request with authentication headers
return {
url: `https://api.example.com${path}?${new URLSearchParams(queryParams)}`,
method,
headers: {
'Content-Type': 'application/json',
'X-Api-Key': apiKey,
'X-Timestamp': timestamp,
'X-Signature': signature
},
body: body || {},
// For debugging/verification
stringToSign
};
}
// Simulate API server verification
function verifyApiRequest(apiKey, secretKey, method, path, queryParams, body, timestamp, signature) {
// Recreate the string that was signed
const stringToSign = [
method.toUpperCase(),
path,
new URLSearchParams(queryParams).toString(),
typeof body === 'string' ? body : JSON.stringify(body || {}),
timestamp
].join('\n');
// Verify HMAC signature
const hmac = crypto.createHmac('sha256', secretKey);
hmac.update(stringToSign);
const expectedSignature = hmac.digest('hex');
return {
isValid: crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
),
expectedSignature
};
}
// API credentials
const apiKey = 'user123';
const secretKey = 'very-secret-api-key';
// Create a request
const timestamp = new Date().toISOString();
const request = createApiRequest(
apiKey,
secretKey,
'POST',
'/api/v1/users',
{ filter: 'active' },
{ name: 'John Doe', email: 'john@example.com' },
timestamp
);
console.log('API Request:');
console.log(`URL: ${request.url}`);
console.log(`Method: ${request.method}`);
console.log('Headers:', request.headers);
console.log('Body:', request.body);
console.log('\nString that was signed:');
console.log(request.stringToSign);
// Server verifies the request
const verification = verifyApiRequest(
apiKey,
secretKey,
'POST',
'/api/v1/users',
{ filter: 'active' },
{ name: 'John Doe', email: 'john@example.com' },
timestamp,
request.headers['X-Signature']
);
console.log('\nVerification result:');
console.log(`Is signature valid? ${verification.isValid}`);
// Try with tampered data
const tamperedVerification = verifyApiRequest(
apiKey,
secretKey,
'POST',
'/api/v1/users',
{ filter: 'active' },
{ name: 'Jane Doe', email: 'jane@example.com' }, // Changed body
timestamp,
request.headers['X-Signature']
);
console.log('\nTampered verification result:');
console.log(`Is signature valid? ${tamperedVerification.isValid}`);