Skip to main content

Cryptography Guide

Learn how to use cryptographic functions in your Invoke functions.

Overview

import crypto from 'crypto'

export default function handler(req, res) {
const data = req.body?.data ?? 'Hello World'
const hash = crypto.createHash('sha256').update(data).digest('hex')
res.json({ hash })
}

Hashing

SHA-256 Hash

import crypto from 'crypto'

export default function handler(req, res) {
const data = req.body.data || 'Hello World'
const hash = crypto.createHash('sha256').update(data).digest('hex')
res.json({ hash })
}

Multiple Hashing Algorithms

import crypto from 'crypto'

export default function handler(req, res) {
const data = req.body.data || 'secret data'

res.json({
md5: crypto.createHash('md5').update(data).digest('hex'),
sha1: crypto.createHash('sha1').update(data).digest('hex'),
sha256: crypto.createHash('sha256').update(data).digest('hex'),
sha512: crypto.createHash('sha512').update(data).digest('hex')
})
}

HMAC (Message Authentication)

Create HMAC

import crypto from 'crypto'

export default function handler(req, res) {
const secret = process.env.HMAC_SECRET || 'my-secret-key'
const message = req.body.message || 'Hello World'

const hmac = crypto.createHmac('sha256', secret).update(message).digest('hex')
res.json({ message, hmac })
}

Verify HMAC

import crypto from 'crypto'

function verifyHMAC(message, receivedHMAC, secret) {
const expected = crypto.createHmac('sha256', secret).update(message).digest('hex')
return crypto.timingSafeEqual(Buffer.from(receivedHMAC), Buffer.from(expected))
}

export default function handler(req, res) {
const { message, hmac } = req.body
const secret = process.env.HMAC_SECRET
res.json({ valid: verifyHMAC(message, hmac, secret) })
}

Symmetric Encryption (AES)

Encrypt Data

import crypto from 'crypto'

function encrypt(text, password) {
const key = crypto.pbkdf2Sync(password, 'salt', 100000, 32, 'sha256')
const iv = crypto.randomBytes(16)
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv)
let encrypted = cipher.update(text, 'utf8', 'hex')
encrypted += cipher.final('hex')
return { encrypted, iv: iv.toString('hex') }
}

export default function handler(req, res) {
const { text, password } = req.body
res.json(encrypt(text, password))
}

Decrypt Data

import crypto from 'crypto'

function decrypt(encrypted, password, ivHex) {
const key = crypto.pbkdf2Sync(password, 'salt', 100000, 32, 'sha256')
const iv = Buffer.from(ivHex, 'hex')
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
let decrypted = decipher.update(encrypted, 'hex', 'utf8')
decrypted += decipher.final('utf8')
return decrypted
}

export default function handler(req, res) {
const { encrypted, password, iv } = req.body
res.json({ decrypted: decrypt(encrypted, password, iv) })
}

Asymmetric Encryption (RSA)

Generate Key Pair

import crypto from 'crypto'

export default function handler(req, res) {
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
})
res.json({ publicKey, privateKey })
}

Encrypt / Decrypt with RSA

import crypto from 'crypto'

export default function handler(req, res) {
const { action, data, publicKey, privateKey } = req.body

if (action === 'encrypt') {
const encrypted = crypto.publicEncrypt(publicKey, Buffer.from(data))
return res.json({ encrypted: encrypted.toString('base64') })
}

if (action === 'decrypt') {
const decrypted = crypto.privateDecrypt(privateKey, Buffer.from(data, 'base64'))
return res.json({ decrypted: decrypted.toString() })
}

res.status(400).json({ error: 'Unknown action' })
}

Digital Signatures

Sign and Verify

import crypto from 'crypto'

export default function handler(req, res) {
const { action, data, privateKey, publicKey, signature } = req.body

if (action === 'sign') {
const sig = crypto.sign('sha256', Buffer.from(data), privateKey)
return res.json({ signature: sig.toString('base64') })
}

if (action === 'verify') {
const valid = crypto.verify('sha256', Buffer.from(data), publicKey, Buffer.from(signature, 'base64'))
return res.json({ valid })
}

res.status(400).json({ error: 'Unknown action' })
}

Random Data Generation

import crypto from 'crypto'

export default function handler(req, res) {
const bytes = crypto.randomBytes(32).toString('hex')
const uuid = crypto.randomUUID()
const randomInt = crypto.randomInt(1, 100)

res.json({ bytes, uuid, randomInt })
}

Password Hashing

import crypto from 'crypto'

function hashPassword(password) {
const salt = crypto.randomBytes(16).toString('hex')
const hash = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha512').toString('hex')
return { salt, hash }
}

function verifyPassword(password, salt, storedHash) {
const hash = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha512').toString('hex')
return hash === storedHash
}

export default async function handler(req, res) {
const { action, password } = req.body

if (action === 'register') {
const { salt, hash } = hashPassword(password)
await kv.set('user:password', { salt, hash })
return res.json({ success: true })
}

if (action === 'login') {
const stored = await kv.get('user:password')
const authenticated = verifyPassword(password, stored.salt, stored.hash)
return res.json({ authenticated })
}

res.status(400).json({ error: 'Unknown action' })
}

Best Practices

1. Use Strong Keys

// ❌ Weak
const key = 'password123'

// ✅ Strong
const key = crypto.randomBytes(32)

2. Store Secrets Securely

// ❌ Don't hardcode
const apiKey = 'hardcoded-secret'

// ✅ Use environment variables
const apiKey = process.env.API_KEY

3. Use Timing-Safe Comparisons

// ❌ Vulnerable to timing attacks
if (receivedToken === expectedToken) { ... }

// ✅ Timing-safe
const isEqual = crypto.timingSafeEqual(
Buffer.from(receivedToken), Buffer.from(expectedToken))

Next Steps