Cryptographic Tools for AI Agents: Hashing via MCP

When an AI agent needs to verify a webhook signature or hash a password, it faces an impossible task. LLMs fundamentally cannot compute cryptographic hashes - they can only make them up. MCP hashing tools give agents real cryptographic capabilities.

Why LLMs Can't Hash

Cryptographic hashing is a one-way mathematical function that transforms input data into a fixed-size output. SHA256, for example, processes data in 512-bit blocks through 64 rounds of bitwise operations, additions, and rotations.

LLMs work completely differently. They predict the next token based on patterns in training data. When asked for a SHA256 hash, an LLM will generate something that looks like a hash (64 hexadecimal characters) but has no mathematical relationship to the input.

LLM Hash vs Real Hash
Input: "Hello, World!"

// LLM might generate (fabricated):
"7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"

// Actual SHA256 (computed):
"dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f"

// These are completely different!
// The LLM's hash is meaningless.
Security Critical: Using fabricated hashes in production could lead to authentication bypasses, data integrity failures, and security vulnerabilities. Always use deterministic tools for cryptographic operations.

SHA256 and MD5 via MCP

TinyFn provides all common hashing algorithms through MCP:

SHA256 Hashing

SHA256 is the industry standard for secure hashing:

MCP Tool Call: SHA256
Tool: hash/sha256
Input: {
  "text": "Hello, World!"
}

Response: {
  "hash": "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f",
  "algorithm": "sha256",
  "input_length": 13
}

MD5 Hashing

MD5 is fast but cryptographically weak - use only for checksums, never for security:

MCP Tool Call: MD5
Tool: hash/md5
Input: {
  "text": "Hello, World!"
}

Response: {
  "hash": "65a8e27d8879283831b664bd8b7f0ad4",
  "algorithm": "md5",
  "input_length": 13
}

SHA512 for Maximum Security

MCP Tool Call: SHA512
Tool: hash/sha512
Input: {
  "text": "Hello, World!"
}

Response: {
  "hash": "374d794a95cdcfd8b35993185fef9ba368f160d8daf432d08ba9f1ed1e5abe6cc69291e0fa2fe0006a52570ef18c19def4e617c33ce52ef0a6e5fbe318cb0387",
  "algorithm": "sha512",
  "input_length": 13
}

HMAC for Webhook Verification

HMAC (Hash-based Message Authentication Code) combines a hash function with a secret key. It's essential for verifying that webhook payloads haven't been tampered with and come from legitimate sources.

How Webhook Signatures Work

  1. The sender (e.g., Stripe, GitHub) computes HMAC of the payload using a shared secret
  2. The signature is sent in a header (e.g., X-Hub-Signature-256)
  3. Your agent computes HMAC of the received payload
  4. If signatures match, the payload is authentic
MCP Tool Call: HMAC-SHA256
Tool: hash/hmac
Input: {
  "text": "{\"event\":\"payment.completed\",\"amount\":9900}",
  "key": "whsec_your_webhook_secret",
  "algorithm": "sha256"
}

Response: {
  "hmac": "5d41402abc4b2a76b9719d911017c592",
  "algorithm": "hmac-sha256"
}

Webhook Verification Example

Verifying a GitHub Webhook
// Incoming webhook
Headers: {
  "X-Hub-Signature-256": "sha256=5d41402abc4b2a76b9719d911017c592"
}
Body: {"action":"push","repository":"myrepo"}

// Agent verification flow:
1. Extract signature from header
2. Call hash/hmac with body and secret
3. Compare: signature === "sha256=" + hmac_result
4. If match: process webhook
   If mismatch: reject as potentially forged

Security Best Practices

Never Use MD5 for Security

MD5 has known collision vulnerabilities. Use it only for non-security checksums (file deduplication, cache keys). For anything security-related, use SHA256 or stronger.

Use Timing-Safe Comparison

When comparing hashes, use constant-time comparison to prevent timing attacks:

Timing-Safe Comparison
// Bad - vulnerable to timing attacks
if (computed_hash === provided_hash) { ... }

// Good - constant time comparison
import { timingSafeEqual } from 'crypto';
const a = Buffer.from(computed_hash);
const b = Buffer.from(provided_hash);
if (a.length === b.length && timingSafeEqual(a, b)) { ... }

Hash Passwords Properly

For password storage, don't use SHA256 directly. Use password-specific algorithms like bcrypt or Argon2 that include salt and are intentionally slow:

Password Hashing
// Not recommended for passwords (too fast, no salt)
Tool: hash/sha256
Input: { "text": "user_password" }

// Recommended for passwords
Tool: hash/bcrypt
Input: {
  "password": "user_password",
  "rounds": 12
}

Response: {
  "hash": "$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/X4.VTtYNPmVYVJtKG"
}

Verify Data Integrity

Use hashes to verify files and data haven't been modified:

File Integrity Check
// When storing file
Tool: hash/sha256
Input: { "text": file_contents }
// Store hash: "a591a6d40bf420404a011733cfb7b190..."

// When retrieving file
Tool: hash/sha256
Input: { "text": retrieved_contents }
// Compare with stored hash to verify integrity

Implementation Examples

Python: Webhook Verification Agent

import requests
import hmac
import hashlib

class WebhookAgent:
    def __init__(self, api_key, webhook_secret):
        self.api_key = api_key
        self.webhook_secret = webhook_secret
        self.base_url = "https://api.tinyfn.io/v1"

    def compute_hmac(self, payload):
        """Compute HMAC-SHA256 using TinyFn"""
        response = requests.post(
            f"{self.base_url}/hash/hmac",
            headers={
                "X-API-Key": self.api_key,
                "Content-Type": "application/json"
            },
            json={
                "text": payload,
                "key": self.webhook_secret,
                "algorithm": "sha256"
            }
        )
        return response.json()["hmac"]

    def verify_webhook(self, payload, signature_header):
        """Verify webhook signature"""
        computed = self.compute_hmac(payload)
        expected = signature_header.replace("sha256=", "")

        # Timing-safe comparison
        return hmac.compare_digest(computed, expected)

    def hash_for_storage(self, data):
        """Generate SHA256 hash for data integrity"""
        response = requests.post(
            f"{self.base_url}/hash/sha256",
            headers={
                "X-API-Key": self.api_key,
                "Content-Type": "application/json"
            },
            json={"text": data}
        )
        return response.json()["hash"]

# Usage
agent = WebhookAgent("your-api-key", "webhook-secret")

# Verify incoming webhook
payload = '{"event":"payment.completed"}'
signature = "sha256=abc123..."
is_valid = agent.verify_webhook(payload, signature)

if is_valid:
    print("Webhook verified, processing...")
else:
    print("Invalid signature, rejecting webhook")

JavaScript: Security Agent

import { timingSafeEqual } from 'crypto';

class SecurityAgent {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.tinyfn.io/v1';
  }

  async sha256(text) {
    const response = await fetch(`${this.baseUrl}/hash/sha256`, {
      method: 'POST',
      headers: {
        'X-API-Key': this.apiKey,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ text })
    });
    return (await response.json()).hash;
  }

  async hmacSha256(text, key) {
    const response = await fetch(`${this.baseUrl}/hash/hmac`, {
      method: 'POST',
      headers: {
        'X-API-Key': this.apiKey,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ text, key, algorithm: 'sha256' })
    });
    return (await response.json()).hmac;
  }

  async verifySignature(payload, signature, secret) {
    const computed = await this.hmacSha256(payload, secret);

    // Timing-safe comparison
    const a = Buffer.from(computed);
    const b = Buffer.from(signature);

    return a.length === b.length && timingSafeEqual(a, b);
  }

  async hashPassword(password) {
    const response = await fetch(`${this.baseUrl}/hash/bcrypt`, {
      method: 'POST',
      headers: {
        'X-API-Key': this.apiKey,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ password, rounds: 12 })
    });
    return (await response.json()).hash;
  }
}

// Usage
const agent = new SecurityAgent('your-api-key');

// Hash user password for storage
const passwordHash = await agent.hashPassword('user-password-123');
console.log('Store this hash:', passwordHash);

// Verify API signature
const isValid = await agent.verifySignature(
  '{"data":"example"}',
  'abc123signature',
  'api-secret-key'
);
console.log('Signature valid:', isValid);

Complete Hash Tool Reference

TinyFn provides a comprehensive set of hashing tools via MCP:

Tool Description Use Case
hash/sha256 SHA-256 hash (256-bit) General security, signatures
hash/sha384 SHA-384 hash (384-bit) TLS certificates
hash/sha512 SHA-512 hash (512-bit) High-security applications
hash/sha3 SHA-3 hash family Latest standard
hash/md5 MD5 hash (128-bit) Checksums only (not security)
hash/hmac HMAC with any algorithm Webhook verification, API auth
hash/bcrypt bcrypt password hash Password storage
hash/blake2 BLAKE2 hash Fast secure hashing
hash/crc32 CRC32 checksum Data integrity
hash/compare Compare two hashes Verification

Add Crypto Tools to Your AI Agent

Give your agents real hashing capabilities. Get your free TinyFn API key.

Get Free API Key

Ready to try TinyFn?

Get your free API key and start building in minutes.

Get Free API Key