Testing Environment: Our tools are currently under heavy testing. You may experience slower performance or temporary issues.

🔐

HMAC Generator

Generate HMAC (Hash-based Message Authentication Codes) using various hash algorithms

Quick Presets

HMAC Generation

Characters: 0 | Bytes: 0
Excellent: Industry standard

✅ Recommended

SHA256:Industry Standard
SHA512:High Security
SHA3:Latest Standard

⚠️ Legacy

SHA1:Deprecated
MD5:Avoid
Use only for backward compatibility

📱 Use Cases

• API request authentication
• JWT token signing
• Webhook verification
• Data integrity checking
• Message authentication

🔐 HMAC Security Tips

  • Strong Keys: Use cryptographically random keys with sufficient length
  • Key Management: Store keys securely, rotate regularly, never hardcode
  • Algorithm Choice: Use SHA-256 or SHA-512 for new applications
  • Constant-Time Comparison: Always use constant-time comparison for verification
  • Include Timestamps: Add timestamps to prevent replay attacks

About HMAC (Hash-based Message Authentication Code)

HMAC is a cryptographic mechanism that combines a secret key with a hash function to provide message authentication and data integrity verification. It's widely used in API authentication, JWT tokens, and secure communication protocols.

  • Combines secret key with hash function for authentication
  • Provides both data integrity and authenticity verification
  • Resistant to length extension attacks (unlike simple keyed hashing)
  • Used in OAuth, JWT, API signatures, and SSL/TLS protocols
  • Supports multiple hash algorithms: SHA-256, SHA-512, MD5

HMAC vs Simple Hashing

HMAC Advantages

  • Authentication: Verifies message sender identity
  • Integrity: Detects message tampering
  • Secret Key: Only parties with key can generate/verify
  • Attack Resistant: Secure against length extension
  • Standardized: FIPS 198 and RFC 2104 compliant

Simple Hash Limitations

  • No Authentication: Anyone can compute hash
  • Vulnerable: Simple key concatenation is insecure
  • Length Extension: Attackers can extend messages
  • No Secret: Hash values can be computed by anyone
  • Limited Use: Only provides data integrity

Advertisement

AdSense Banner Ad Placeholder

Frequently Asked Questions

What's the difference between HMAC and digital signatures?

HMAC uses symmetric cryptography (same secret key for generation and verification), while digital signatures use asymmetric cryptography (private key signs, public key verifies). HMAC is faster but requires shared secrets, while signatures provide non-repudiation.

Which hash algorithm should I use with HMAC?

Use SHA-256 for most applications as it provides excellent security and performance. SHA-512 offers higher security for sensitive applications. Avoid MD5 and SHA-1 for new implementations due to known vulnerabilities, though they may be required for legacy system compatibility.

How should I manage HMAC keys securely?

Generate cryptographically random keys with sufficient length (at least 32 bytes for SHA-256). Store keys securely using key management systems, rotate them regularly, and never hardcode them in source code. Use environment variables or secure vaults for key storage.

Can I use the same HMAC key for multiple purposes?

It's better to use different keys for different purposes to limit the impact of key compromise. If you must reuse keys, ensure they're used only for the same type of data and security context. Consider key derivation functions to generate purpose-specific keys from a master key.

HMAC Examples

HMAC-SHA256 Example:

Message:
"Hello, World!"
Secret Key:
"my-secret-key-123"
HMAC-SHA256:
4e99726...f8a2b1c
Length: 64 hex characters

HMAC Process:

1. Key Preparation
Pad/Hash: Adjust key to block size
XOR ipad: Key ⊕ 0x36 repeated
XOR opad: Key ⊕ 0x5C repeated
2. Inner Hash
Compute: H(K ⊕ ipad || message)
Result: Inner hash value
3. Outer Hash
Compute: H(K ⊕ opad || inner_hash)
Result: Final HMAC value

Sponsored Content

AdSense Square Ad Placeholder

HMAC Implementation

JavaScript HMAC Generator:

class HMACGenerator {
  constructor() {
    this.supportedAlgorithms = [
      'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512', 'MD5'
    ];
    
    this.blockSizes = {
      'SHA-1': 64,
      'SHA-256': 64,
      'SHA-384': 128,
      'SHA-512': 128,
      'MD5': 64
    };
    
    this.outputSizes = {
      'SHA-1': 20,
      'SHA-256': 32,
      'SHA-384': 48,
      'SHA-512': 64,
      'MD5': 16
    };
  }
  
  // Generate HMAC using Web Crypto API
  async generateHMAC(message, key, algorithm = 'SHA-256') {
    try {
      if (typeof message !== 'string') {
        return {
          success: false,
          error: 'Message must be a string'
        };
      }
      
      if (typeof key !== 'string') {
        return {
          success: false,
          error: 'Key must be a string'
        };
      }
      
      if (!this.supportedAlgorithms.includes(algorithm)) {
        return {
          success: false,
          error: `Unsupported algorithm: ${algorithm}`
        };
      }
      
      const startTime = performance.now();
      
      let hmac;
      if (this.isWebCryptoSupported(algorithm)) {
        hmac = await this.webCryptoHMAC(message, key, algorithm);
      } else {
        hmac = await this.fallbackHMAC(message, key, algorithm);
      }
      
      const endTime = performance.now();
      
      return {
        success: true,
        message: message,
        key: '***hidden***',
        algorithm: algorithm,
        hmac: hmac,
        hmacUppercase: hmac.toUpperCase(),
        length: hmac.length,
        bytes: this.outputSizes[algorithm],
        timing: {
          duration: Math.round(endTime - startTime),
          formatted: `${Math.round(endTime - startTime)}ms`
        },
        verification: this.generateVerificationInfo(message, hmac, algorithm),
        formats: this.getHMACFormats(hmac)
      };
      
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
  
  // Use Web Crypto API for HMAC generation
  async webCryptoHMAC(message, key, algorithm) {
    const encoder = new TextEncoder();
    const keyData = encoder.encode(key);
    const messageData = encoder.encode(message);
    
    // Import the key
    const cryptoKey = await crypto.subtle.importKey(
      'raw',
      keyData,
      {
        name: 'HMAC',
        hash: algorithm
      },
      false,
      ['sign']
    );
    
    // Generate HMAC
    const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData);
    const hashArray = Array.from(new Uint8Array(signature));
    
    return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
  }
  
  // Check Web Crypto API support
  isWebCryptoSupported(algorithm) {
    const supported = ['SHA-1', 'SHA-256', 'SHA-384', 'SHA-512'];
    return supported.includes(algorithm);
  }
  
  // Fallback HMAC implementation
  async fallbackHMAC(message, key, algorithm) {
    if (algorithm === 'MD5') {
      return this.hmacMD5(message, key);
    }
    
    throw new Error(`Fallback not implemented for ${algorithm}`);
  }
  
  // Simple HMAC-MD5 implementation (for demonstration)
  async hmacMD5(message, key) {
    const blockSize = this.blockSizes['MD5'];
    const ipad = 0x36;
    const opad = 0x5C;
    
    // Prepare key
    let keyBytes = this.stringToBytes(key);
    
    // If key is longer than block size, hash it
    if (keyBytes.length > blockSize) {
      keyBytes = await this.simpleMD5Bytes(keyBytes);
    }
    
    // Pad key to block size
    while (keyBytes.length < blockSize) {
      keyBytes.push(0);
    }
    
    // Create inner and outer key pads
    const innerKeyPad = keyBytes.map(b => b ^ ipad);
    const outerKeyPad = keyBytes.map(b => b ^ opad);
    
    // Inner hash: H(K ⊕ ipad || message)
    const messageBytes = this.stringToBytes(message);
    const innerData = innerKeyPad.concat(messageBytes);
    const innerHash = await this.simpleMD5Bytes(innerData);
    
    // Outer hash: H(K ⊕ opad || innerHash)
    const outerData = outerKeyPad.concat(innerHash);
    const finalHash = await this.simpleMD5Bytes(outerData);
    
    return finalHash.map(b => b.toString(16).padStart(2, '0')).join('');
  }
  
  // Convert string to byte array
  stringToBytes(str) {
    const bytes = [];
    for (let i = 0; i < str.length; i++) {
      bytes.push(str.charCodeAt(i) & 0xFF);
    }
    return bytes;
  }
  
  // Simplified MD5 for demonstration (use proper library in production)
  async simpleMD5Bytes(bytes) {
    // This is a placeholder - use a proper MD5 implementation
    const str = String.fromCharCode.apply(null, bytes);
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash;
    }
    
    const result = [];
    for (let i = 0; i < 16; i++) {
      result.push((hash >>> (i * 2)) & 0xFF);
    }
    return result;
  }
  
  // Verify HMAC
  async verifyHMAC(message, key, expectedHMAC, algorithm = 'SHA-256') {
    try {
      const result = await this.generateHMAC(message, key, algorithm);
      
      if (!result.success) {
        return result;
      }
      
      const matches = this.constantTimeCompare(
        result.hmac.toLowerCase(),
        expectedHMAC.toLowerCase()
      );
      
      return {
        success: true,
        matches: matches,
        message: message,
        algorithm: algorithm,
        expected: expectedHMAC.toLowerCase(),
        actual: result.hmac.toLowerCase(),
        verdict: matches ? 'VERIFIED' : 'FAILED',
        timing: result.timing
      };
      
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
  
  // Constant time comparison to prevent timing attacks
  constantTimeCompare(a, b) {
    if (a.length !== b.length) return false;
    
    let result = 0;
    for (let i = 0; i < a.length; i++) {
      result |= a.charCodeAt(i) ^ b.charCodeAt(i);
    }
    
    return result === 0;
  }
  
  // Generate HMAC for multiple messages
  async generateBatchHMAC(messages, key, algorithm = 'SHA-256') {
    const results = [];
    
    for (const message of messages) {
      const result = await this.generateHMAC(message, key, algorithm);
      results.push({
        message: message,
        ...result
      });
    }
    
    return {
      success: true,
      key: '***hidden***',
      algorithm: algorithm,
      count: messages.length,
      results: results
    };
  }
  
  // Generate JWT-style HMAC signature
  async generateJWTSignature(header, payload, secret, algorithm = 'SHA-256') {
    try {
      // Encode header and payload
      const encodedHeader = this.base64UrlEncode(JSON.stringify(header));
      const encodedPayload = this.base64UrlEncode(JSON.stringify(payload));
      
      // Create signing input
      const signingInput = `${encodedHeader}.${encodedPayload}`;
      
      // Generate HMAC
      const hmacResult = await this.generateHMAC(signingInput, secret, algorithm);
      
      if (!hmacResult.success) {
        return hmacResult;
      }
      
      // Convert hex HMAC to base64url
      const hmacBytes = this.hexToBytes(hmacResult.hmac);
      const signature = this.base64UrlEncodeBytes(hmacBytes);
      
      const jwt = `${signingInput}.${signature}`;
      
      return {
        success: true,
        header: header,
        payload: payload,
        algorithm: algorithm,
        signingInput: signingInput,
        hmac: hmacResult.hmac,
        signature: signature,
        jwt: jwt,
        parts: {
          header: encodedHeader,
          payload: encodedPayload,
          signature: signature
        }
      };
      
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
  
  // Base64 URL encode
  base64UrlEncode(str) {
    return btoa(str)
      .replace(/=/g, '')
      .replace(/\+/g, '-')
      .replace(/\//g, '_');
  }
  
  // Base64 URL encode bytes
  base64UrlEncodeBytes(bytes) {
    const str = String.fromCharCode.apply(null, bytes);
    return btoa(str)
      .replace(/=/g, '')
      .replace(/\+/g, '-')
      .replace(/\//g, '_');
  }
  
  // Convert hex string to bytes
  hexToBytes(hex) {
    const bytes = [];
    for (let i = 0; i < hex.length; i += 2) {
      bytes.push(parseInt(hex.substr(i, 2), 16));
    }
    return bytes;
  }
  
  // Generate API signature (common pattern)
  async generateAPISignature(httpMethod, uri, params, secret, algorithm = 'SHA-256') {
    try {
      // Sort parameters
      const sortedParams = Object.keys(params)
        .sort()
        .map(key => `${key}=${params[key]}`)
        .join('&');
      
      // Create signature base string
      const signatureBase = `${httpMethod.toUpperCase()}&${uri}&${sortedParams}`;
      
      // Generate HMAC
      const hmacResult = await this.generateHMAC(signatureBase, secret, algorithm);
      
      if (!hmacResult.success) {
        return hmacResult;
      }
      
      return {
        success: true,
        method: httpMethod.toUpperCase(),
        uri: uri,
        params: params,
        sortedParams: sortedParams,
        signatureBase: signatureBase,
        hmac: hmacResult.hmac,
        algorithm: algorithm,
        usage: 'Add to request headers or query parameters'
      };
      
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
  
  // Generate key from password (PBKDF2-like)
  async generateKeyFromPassword(password, salt = 'default-salt', iterations = 1000) {
    const encoder = new TextEncoder();
    const passwordData = encoder.encode(password);
    const saltData = encoder.encode(salt);
    
    // Import password as key material
    const keyMaterial = await crypto.subtle.importKey(
      'raw',
      passwordData,
      'PBKDF2',
      false,
      ['deriveBits']
    );
    
    // Derive key
    const derivedKey = await crypto.subtle.deriveBits(
      {
        name: 'PBKDF2',
        salt: saltData,
        iterations: iterations,
        hash: 'SHA-256'
      },
      keyMaterial,
      256 // 32 bytes
    );
    
    const keyArray = Array.from(new Uint8Array(derivedKey));
    const keyHex = keyArray.map(b => b.toString(16).padStart(2, '0')).join('');
    
    return {
      success: true,
      password: '***hidden***',
      salt: salt,
      iterations: iterations,
      key: keyHex,
      keyBytes: keyArray,
      usage: 'Use this derived key for HMAC generation'
    };
  }
  
  // Get verification information
  generateVerificationInfo(message, hmac, algorithm) {
    return {
      howToVerify: 'Generate HMAC with same message, key, and algorithm',
      steps: [
        '1. Use the same secret key',
        '2. Apply same hash algorithm (' + algorithm + ')',
        '3. Generate HMAC for the message',
        '4. Compare results using constant-time comparison'
      ],
      security: 'Never share the secret key used for HMAC generation'
    };
  }
  
  // Get HMAC in different formats
  getHMACFormats(hmac) {
    return {
      hex: hmac.toLowerCase(),
      hexUpper: hmac.toUpperCase(),
      base64: btoa(hmac.match(/.{2}/g)?.map(hex => 
        String.fromCharCode(parseInt(hex, 16))).join('') || ''),
      withColons: hmac.match(/.{2}/g)?.join(':'),
      withSpaces: hmac.match(/.{2}/g)?.join(' '),
      withDashes: hmac.match(/.{4}/g)?.join('-')
    };
  }
  
  // Benchmark HMAC algorithms
  async benchmarkHMAC(message = 'benchmark test', key = 'test-key', iterations = 100) {
    const algorithms = ['SHA-1', 'SHA-256', 'SHA-512'];
    const results = [];
    
    for (const algorithm of algorithms) {
      const startTime = performance.now();
      
      for (let i = 0; i < iterations; i++) {
        await this.generateHMAC(message + i, key, algorithm);
      }
      
      const endTime = performance.now();
      const avgTime = (endTime - startTime) / iterations;
      
      results.push({
        algorithm: algorithm,
        iterations: iterations,
        totalTime: Math.round(endTime - startTime),
        averageTime: Math.round(avgTime * 100) / 100,
        hmacsPerSecond: Math.round(1000 / avgTime),
        outputSize: this.outputSizes[algorithm],
        blockSize: this.blockSizes[algorithm]
      });
    }
    
    return {
      success: true,
      message: message,
      key: '***hidden***',
      iterations: iterations,
      results: results.sort((a, b) => a.averageTime - b.averageTime),
      recommendation: this.getRecommendation(results)
    };
  }
  
  // Get algorithm recommendation
  getRecommendation(benchmarkResults) {
    const sha256 = benchmarkResults.find(r => r.algorithm === 'SHA-256');
    
    return {
      algorithm: 'SHA-256',
      reason: 'Best balance of security, performance, and compatibility',
      performance: sha256?.averageTime || 'unknown',
      alternatives: {
        'SHA-512': 'Higher security, larger output size',
        'SHA-1': 'Legacy compatibility only (not recommended for new projects)'
      }
    };
  }
}

// Usage examples
const hmac = new HMACGenerator();

// Generate HMAC
console.log('Generate HMAC:');
const message = 'Hello, World!';
const secretKey = 'my-secret-key-123';
const hmacResult = await hmac.generateHMAC(message, secretKey, 'SHA-256');
console.log(hmacResult);

// Verify HMAC
console.log('\nVerify HMAC:');
if (hmacResult.success) {
  const verification = await hmac.verifyHMAC(message, secretKey, hmacResult.hmac, 'SHA-256');
  console.log(verification);
}

// JWT Signature
console.log('\nJWT Signature:');
const header = { alg: 'HS256', typ: 'JWT' };
const payload = { sub: '1234567890', name: 'John Doe', iat: 1516239022 };
const jwt = await hmac.generateJWTSignature(header, payload, 'secret', 'SHA-256');
console.log(jwt);

// API Signature
console.log('\nAPI Signature:');
const apiSig = await hmac.generateAPISignature('GET', '/api/users', 
  { id: '123', timestamp: '1609459200' }, 'api-secret');
console.log(apiSig);

console.log('HMAC generator ready!');
            

API Authentication with HMAC

Request Signing:

Method: POST /api/payments
Body: {"amount": 100, "currency": "USD"}
Timestamp: 1640995200
Signature Base: POST|/api/payments|body+timestamp
HMAC-SHA256: a1b2c3d4e5f6...
Header: Authorization: HMAC a1b2c3d4e5f6...

Verification Process:

1. Extract signature from Authorization header
2. Reconstruct signature base string
3. Generate HMAC with server's copy of key
4. Compare signatures using constant-time function
5. Check timestamp to prevent replay attacks
6. Allow/deny request based on verification

HMAC Security Best Practices

  • Strong Keys: Use cryptographically random keys with at least 32 bytes
  • Key Management: Store keys securely, rotate regularly, never hardcode
  • Algorithm Choice: Use SHA-256 or SHA-512, avoid MD5 and SHA-1
  • Constant-Time Comparison: Prevent timing attacks when verifying HMACs
  • Include Timestamps: Add timestamps to prevent replay attacks
  • Separate Keys: Use different keys for different purposes
  • Validate Input: Always validate message content before HMAC generation

Common Use Cases

  • API request authentication and authorization
  • JWT token signing and verification
  • Webhook payload verification
  • Message integrity in communications
  • Session token generation and validation
  • File integrity verification systems
  • OAuth signature generation
  • Database audit trail verification

Advertisement

AdSense Bottom Ad Placeholder