Inslash Icon

Documentation

Everything you need to integrate Inslash into your application

1. Get Your Credentials

Before using Inslash, you need an API key to access our secure hashing infrastructure.

  1. Sign Up: Create an account at inslash-q5s6.vercel.app/
  2. Get API Key: Navigate to the API Keys section in your dashboard.
  3. Save It: Copy the key (starts with sk_) - you'll need it for the next step.

2. Choose Integration

Option A: Node.js Library (Recommended)

Best for Node.js applications. Provides type safety, automatic fallback, and utility helpers.

Installation

npm install inslash

Usage

const inslash = require('inslash');

// Configuration
inslash.configure({
    apiKey: 'sk_test_51Mz...', 
    apiUrl: 'https://inslash-q5s6.vercel.app/'
});

const { hash } = inslash;

async function example() {
    // Hash password (using API with local fallback)
    const { passport } = await hash('password123', 'your-pepper-secret');
    
    // Store passport in DB
    console.log(passport); 
}

Option B: REST API

Best for non-Node.js environments (Python, Go, PHP) or serverless functions.

POST /api/hash Hash Password

Generates a secure hash (passport).

POST /api/verify Verify Password

Verifies a password against a passport.

POST /api/batch-verify Batch Verify

Verify multiple users in a single request.

POST /api/inspect Inspect

Extract metadata and history from any passport.

POST /api/security Security Score

Get a 0-100 security score and recommendations.

Key Management

GET /api/keys List API Keys
POST /api/keys/create Create Key
POST /api/keys/:id/revoke Revoke Key

Example Request (JavaScript/Fetch)

const response = await fetch('https://inslash-q5s6.vercel.app//api/hash', {
  method: 'POST',
  headers: {
    'x-api-key': 'sk_test_...', // Your API Key
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    value: 'userPassword123',
    secret: 'your_pepper_secret'
  })
});

const { passport } = await response.json();

Features

🔐 Multiple Algorithms

Support for SHA-256, SHA-384, and SHA-512 HMAC algorithms

🎫 Passport Encoding

All metadata encoded in a single string for easy storage

⚡ Automatic Upgrades

Detects when hashes need upgrading to stronger algorithms

🛡️ Timing-Safe

Protection against timing attacks with constant-time comparison

Migration Guide

Moving from legacy hashing (like bcrypt or manual PBKDF2) to Inslash is designed to be zero-downtime.

The "Lazy Migration" Strategy

You don't need to re-hash your entire database at once. Instead, upgrade users when they next log in.

async function login(email, password) {
    const user = await db.findUser(email);

    // 1. Check if user is already using Inslash
    if (user.password_hash.startsWith('$inslash$')) {
        const { valid, needsUpgrade, upgradedPassport } = await inslash.verify(password, user.password_hash, secret);
        if (!valid) return false;
        
        if (needsUpgrade) {
            await user.update({ password_hash: upgradedPassport });
        }
    } else {
        // 2. Legacy check (e.g. bcrypt)
        const isLegacyValid = await bcrypt.compare(password, user.password_hash);
        if (!isLegacyValid) return false;

        // 3. Transparently migrate to Inslash
        const { passport } = await inslash.hash(password, secret);
        await user.update({ password_hash: passport });
    }
    
    return true;
}

1. Update Schema

Ensure your password column can hold ~128-256 chars (Passports are longer than bcrypt).

2. Standardize Pepper

Pick a consistent secret key (pepper) to use for all new Inslash hashes.

3. Deploy & Profit

Watch your database legacy hashes disappear as users log back in.

hash(value, secret, options)

Creates a secure hash of a password.

Parameter Type Required Description
value string Required The password to hash
secret string Required Secret key (pepper) for additional security
options object Optional Configuration options

Options

Parameter Type Required Description
algorithm string Optional Hash algorithm: "sha256", "sha384", or "sha512" (default: "sha256")
iterations number Optional Number of iterations (default: 100,000)
saltLength number Optional Length of salt in bytes (default: 16)
hashLength number Optional Length of hash in bytes (default: 32)

Returns

Object containing:

  • passport - Encoded string to store in database
  • hash - The raw hash value
  • salt - The generated salt
  • metadata - Algorithm, iterations, etc.

verify(value, passport, secret, options)

Verifies a password against a stored passport.

Parameter Type Required Description
value string Required The password to verify
passport string Required The stored passport from hash()
secret string Required Same secret key used for hashing
options object Optional Upgrade configuration

Returns

Object containing:

  • valid - Boolean indicating if password is correct
  • needsUpgrade - Boolean indicating if hash should be upgraded
  • upgradedPassport - New passport if upgrade needed
  • metadata - Current hash metadata

Security Presets

v2.0

Use named presets instead of tuning options manually. Presets map to battle-tested option sets.

Preset Algorithm Iterations Salt Hash Use Case
fast sha256 50,000 16 32 Dev / low-stakes
balanced sha256 100,000 16 32 Default / general use
strong ★ sha384 200,000 24 48 Recommended for production
paranoid sha512 400,000 32 64 High-security / financial
const { hash, SECURITY_PRESETS } = require('inslash');

// Use a named preset
const result = await hash('myPassword', secret, { preset: 'strong' });

// Or access preset values directly
console.log(SECURITY_PRESETS.paranoid);
// { iterations: 400000, saltLength: 32, hashLength: 64, algorithm: 'sha512' }

batchVerify(values, passport, secret, options?)

v2.0

Verify multiple values against the same passport. Runs with concurrency control to avoid CPU starvation.

Parameter Type Required Description
values string[] Required Array of values to verify (max 50 per API call)
passport string Required The stored passport from hash()
secret string Required Same secret key used for hashing
options.concurrency number Optional Max parallel verifications (default: 4)

Returns

Array of result objects, each containing:

  • value — the input value
  • valid — boolean
  • needsUpgrade — boolean
  • error — string (if that value failed)
const { batchVerify } = require('inslash');

const results = await batchVerify(
    ['guess1', 'guess2', 'correctPassword'],
    storedPassport,
    secret,
    { concurrency: 4 }
);
// [{ value: 'guess1', valid: false }, { value: 'correctPassword', valid: true, needsUpgrade: false }]

inspectPassport(passport)

v2.0

Decode a passport and read its metadata without verifying. Useful for auditing, debugging, and admin tooling.

Parameter Type Required Description
passport string Required The passport string to inspect

Returns

  • valid — boolean (false if passport is malformed)
  • version, algorithm, iterations, saltLength, hashLength, encoding
  • history — full upgrade audit trail
const { inspectPassport } = require('inslash');

const info = inspectPassport(storedPassport);
console.log(info.algorithm);  // 'sha384'
console.log(info.iterations); // 200000
console.log(info.history);    // [{ date, algorithm, event }]

comparePassports(passport1, passport2)

v2.0

Structurally compare two passports. Does not verify plaintext — only compares encoded metadata and hash values.

Returns

  • sameAlgorithm, sameIterations, sameEncoding, sameSalt, sameHash — booleans
  • identical — true when both hash AND salt match (same passport)
const { comparePassports } = require('inslash');

const cmp = comparePassports(passportA, passportB);
console.log(cmp.sameAlgorithm); // true
console.log(cmp.identical);     // false (different salts)

estimateSecurity(passport)

v2.0

Score a passport's security strength (0–100) and get actionable recommendations.

Scoring Methodology

Algorithm: sha256=25, sha384=35, sha512=40
Iterations: ≥400k=35, ≥200k=28, ≥100k=20, ≥50k=12
Salt length: ≥32=15, ≥16=10
Hash length: ≥64=10, ≥32=7
Upgrade history bonus: +5 (shows active maintenance)

Returns

  • score — 0–100
  • level — Excellent / Strong / Good / Fair / Weak / Critical / Invalid
  • recommendations — string[] of actionable improvements
  • metadata — algorithm, iterations, saltLength, hashLength
const { estimateSecurity } = require('inslash');

const { score, level, recommendations } = estimateSecurity(storedPassport);
console.log(score);           // 78
console.log(level);           // 'Strong'
console.log(recommendations); // ['Consider upgrading to sha512']

generateApiKey(options?)

v2.0

Generate a cryptographically secure API key. Useful for generating tokens, secrets, or session keys.

Parameter Type Required Description
prefix string Optional Key prefix (default: "inslash")
byteLength number Optional Random bytes to generate (default: 32)
encoding string Optional "hex" | "base64" | "base64url" (default: "hex")
const { generateApiKey } = require('inslash');

const key = generateApiKey({ prefix: 'myapp', byteLength: 32 });
console.log(key); // 'myapp_a3f9b2c1...'

deriveKey(password, salt, opts?)

v2.0

Derive a deterministic encryption key from a password using PBKDF2. Use this for symmetric encryption key derivation, not authentication.

Note: Use hash() for password authentication. Use deriveKey() only when you need a deterministic key for encryption (e.g. AES-256).

Parameter Type Required Description
password string Required The password to derive from
salt string Required Hex salt string
opts.iterations number Optional PBKDF2 iterations (default: 200,000)
opts.keyLength number Optional Output key length in bytes (default: 32)
opts.algorithm string Optional sha256 | sha384 | sha512 (default: sha512)

Returns

Promise<Buffer> — the derived key as a Node.js Buffer.

const { deriveKey } = require('inslash');
const crypto = require('crypto');

const salt = crypto.randomBytes(16).toString('hex');
const keyBuffer = await deriveKey('userPassword', salt, {
    iterations: 200_000,
    keyLength: 32,       // 256-bit AES key
    algorithm: 'sha512'
});

// Use keyBuffer with AES-256-GCM for encryption

Example: Complete Authentication System

Full Express.js authentication with login, automatic upgrades, and session management:

const express = require('express');
const session = require('express-session');
const { hash, verify } = require('inslash');
const User = require('./models/User');

const app = express();
app.use(express.json());
app.use(session({
    secret: 'your-session-secret',
    resave: false,
    saveUninitialized: false
}));

// Login endpoint
app.post('/login', async (req, res) => {
    const { email, password } = req.body;

    // Find user
    const user = await User.findOne({ email });
    if (!user) {
        return res.status(401).json({ error: 'Invalid credentials' });
    }

    // Verify password
    const result = await verify(password, user.passport, process.env.HASH_PEPPER);

    if (!result.valid) {
        return res.status(401).json({ error: 'Invalid credentials' });
    }

    // Automatic security upgrade
    if (result.needsUpgrade) {
        user.passport = result.upgradedPassport;
        await user.save();
        console.log('Password hash upgraded for user:', user.email);
    }

    // Create session
    req.session.userId = user._id;
    res.json({ success: true, user: { id: user._id, email: user.email } });
});

// Protected route middleware
function requireAuth(req, res, next) {
    if (!req.session.userId) {
        return res.status(401).json({ error: 'Unauthorized' });
    }
    next();
}

app.get('/dashboard', requireAuth, (req, res) => {
    res.json({ message: 'Welcome to your dashboard!' });
});

app.listen(3000);

Example: User Registration Flow

Complete user registration with validation and secure password storage:

const { hash } = require('inslash');
const User = require('./models/User');

app.post('/signup', async (req, res) => {
    const { username, email, password, confirmPassword } = req.body;

    // Validation
    if (!username || !email || !password) {
        return res.status(400).json({ error: 'All fields required' });
    }

    if (password !== confirmPassword) {
        return res.status(400).json({ error: 'Passwords do not match' });
    }

    if (password.length < 8) {
        return res.status(400).json({ error: 'Password must be at least 8 characters' });
    }

    // Check if user exists
    const existingUser = await User.findOne({ $or: [{ username }, { email }] });
    if (existingUser) {
        return res.status(400).json({ error: 'Username or email already exists' });
    }

    // Hash password with strong settings
    const hashResult = await hash(password, process.env.HASH_PEPPER, {
        algorithm: 'sha512',
        iterations: 150000
    });

    // Create user
    const user = new User({
        username,
        email,
        passport: hashResult.passport,
        createdAt: new Date()
    });

    await user.save();

    // Auto-login after registration
    req.session.userId = user._id;
    res.status(201).json({ success: true, user: { id: user._id, username: user.username, email: user.email } });
});

Example: Password Reset System

Secure password reset with email tokens:

const crypto = require('crypto');
const { hash } = require('inslash');
const User = require('./models/User');
const sendEmail = require('./utils/email');

// Request password reset
app.post('/forgot-password', async (req, res) => {
    const { email } = req.body;

    // Find user
    const user = await User.findOne({ email });
    if (!user) {
        // Don't reveal if email exists
        return res.json({ message: 'If email exists, reset link sent' });
    }

    // Generate reset token
    const resetToken = crypto.randomBytes(32).toString('hex');
    const resetTokenHash = crypto.createHash('sha256').update(resetToken).digest('hex');

    user.resetPasswordToken = resetTokenHash;
    user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
    await user.save();

    // Send email
    const resetUrl = \`https://yourapp.com/reset-password/\${resetToken}\`;
    await sendEmail({
        to: user.email,
        subject: 'Password Reset Request',
        html: \`Click here to reset: \${resetUrl}\`
    });

    res.json({ message: 'If email exists, reset link sent' });
});

// Reset password with token
app.post('/reset-password/:token', async (req, res) => {
    const { password } = req.body;

    // Hash the token to compare
    const resetTokenHash = crypto.createHash('sha256')
        .update(req.params.token)
        .digest('hex');

    // Find user with valid token
    const user = await User.findOne({
        resetPasswordToken: resetTokenHash,
        resetPasswordExpires: { $gt: Date.now() }
    });

    if (!user) {
        return res.status(400).json({ error: 'Invalid or expired token' });
    }

    // Hash new password
    const hashResult = await hash(password, process.env.HASH_PEPPER, {
        algorithm: 'sha512',
        iterations: 150000
    });

    // Update user
    user.passport = hashResult.passport;
    user.resetPasswordToken = undefined;
    user.resetPasswordExpires = undefined;
    await user.save();

    res.json({ success: true, message: 'Password reset successful' });
});

Configuration

Recommended security settings:

Production Recommendation: Use SHA-512 with 150,000+ iterations for maximum security.

// Production configuration
const productionConfig = {
    algorithm: 'sha512', // Strongest algorithm
    iterations: 150000, 
    saltLength: 16,     
    hashLength: 64      
};

// Use it
const result = await hash(password, process.env.HASH_PEPPER, productionConfig);