@bernierllc/crypto-utils
综合密码设施,包括钥匙生成、JWT标志、魔法链接和现代应用的安全散列.
安装
npm install @bernierllc/crypto-utils
快速启动
import {
generateApiKey,
generateAccessToken,
generateEmailMagicLink,
verifyJWT,
constantTimeCompare
} from '@bernierllc/crypto-utils';
// Generate an API key with sensible defaults
const apiKey = await generateApiKey();
console.log(apiKey); // ak_a1b2c3d4e5f6...
// Generate JWT access token
const accessToken = generateAccessToken({
sub: 'user123',
email: '[email protected]'
}, 'your-secret');
// Generate magic link for email authentication
const magicLink = generateEmailMagicLink('user123', '[email protected]', 'your-secret');
// Secure password verification
const isValid = constantTimeCompare(providedPassword, storedPasswordHash);
核心特征
QQ 密钥生成
- 多种算法: 随机字节, UUID v4, 自定义模式
- 多个编码:Hex, Base64, Base58 (比特币风格)
- 安全特性: Entropy验证,相撞探测,安全散列
JWT 托肯斯语
- 标准: RFC 7519 JWT的实施
- 多种算法: HS256, HS384, HS512 (英语)
- 核实: 过期,发行人,受众,主题
QQ 魔法链接
- 电子邮件认证: 安全无密码登录
- 密码重置: 有时间限制的重新设置符号
- URL - 安全: 用于网络兼容的 Base64URL 编码
- TOTP 支持: 基于时间的一次性密码
安全设备
- 常时比较:防止时间攻击
- 密码验证: 安全散列验证
- 托肯验证: 全面安全检查
API 参考
密钥生成
核心生成函数
generateRandomKey(options?)
使用 : crypto.randomBytes。 。 。 .
import { generateRandomKey } from '@bernierllc/crypto-utils';
const result = await generateRandomKey({
length: 32, // Key length in bytes
prefix: 'ak_', // Optional prefix
encoding: 'hex', // 'hex' | 'base64' | 'base58'
validateEntropy: true, // Validate entropy requirements
minEntropyBits: 128, // Minimum entropy in bits
checkUnique: async (key) => !await db.keyExists(key), // Collision check
maxRetries: 5 // Max collision retry attempts
});
console.log(result.key); // Generated key string
console.log(result.entropy); // Estimated entropy in bits
console.log(result.metadata); // Generation metadata
方便职能
预配置带有合理默认的密钥生成器 :
import {
generateApiKey, // ak_ + 32 bytes + hex
generateSecretKey, // sk_ + 48 bytes + base64
generateSessionToken, // sess_ + UUID + base58
generateLicenseKey // lic_ + pattern XXXX-XXXX-XXXX-XXXX
} from '@bernierllc/crypto-utils';
const apiKey = await generateApiKey(); // ak_a1b2c3...
const secret = await generateSecretKey(); // sk_SGVsbG8...
const session = await generateSessionToken(); // sess_23456789...
const license = await generateLicenseKey(); // lic_A1B2-C3D4...
日本 键
脚本生成
generateJWT(payload, secret, options?)
生成带有自定义要求的 JWT 令牌 .
import { generateJWT } from '@bernierllc/crypto-utils';
const token = generateJWT({
sub: 'user123',
email: '[email protected]',
role: 'admin'
}, 'your-jwt-secret', {
algorithm: 'HS256', // HS256 | HS384 | HS512
expiresIn: 3600, // 1 hour in seconds
issuer: 'your-app',
audience: 'api',
includeIssuedAt: true // Include iat claim
});
verifyJWT(token, secret, options?)
校验和验证 JWT 标志 .
import { verifyJWT } from '@bernierllc/crypto-utils';
const result = verifyJWT(token, 'your-jwt-secret', {
issuer: 'your-app', // Expected issuer
audience: 'api', // Expected audience
clockTolerance: 30, // Allow 30 seconds clock skew
ignoreExpiration: false // Enforce expiration
});
if (result.valid) {
console.log('User:', result.payload?.sub);
console.log('Expires in:', result.expiresIn, 'seconds');
} else {
console.error('Invalid token:', result.error);
}
方便调试函数
import {
generateAccessToken, // 1 hour expiry, HS256
generateRefreshToken, // 7 days expiry, HS256
} from '@bernierllc/crypto-utils';
// Generate access token (1 hour expiry)
const accessToken = generateAccessToken({
sub: 'user123',
email: '[email protected]'
}, 'your-secret');
// Generate refresh token (7 days expiry)
const refreshToken = generateRefreshToken({
sub: 'user123'
}, 'your-secret');
魔法链接
电子邮件认证链接
generateMagicLink(userId, email, secret, options?)
生成无密码认证的安全魔法链接 .
import { generateMagicLink } from '@bernierllc/crypto-utils';
const result = generateMagicLink('user123', '[email protected]', 'your-secret', {
expirationMinutes: 15, // Link expires in 15 minutes
action: 'login', // Action type
customData: { // Additional data
ip: '192.168.1.1',
userAgent: 'Mozilla/5.0...'
}
});
const magicUrl = `https://yourapp.com/auth/verify?token=${result.token}`;
console.log('Magic link expires at:', new Date(result.expiresAt));
verifyMagicLink(token, secret, options?)
校验魔法链接符号 .
import { verifyMagicLink } from '@bernierllc/crypto-utils';
const result = verifyMagicLink(token, 'your-secret');
if (result.valid) {
console.log('User ID:', result.payload?.userId);
console.log('Email:', result.payload?.email);
console.log('Action:', result.payload?.action);
console.log('Remaining time:', result.remainingMinutes, 'minutes');
// Authenticate user
await authenticateUser(result.payload.userId);
} else {
console.error('Invalid magic link:', result.error);
}
方便魔法链接函数
import {
generateEmailMagicLink, // 15 min expiry, email_auth action
generatePasswordResetLink // 30 min expiry, password_reset action
} from '@bernierllc/crypto-utils';
// Email verification link
const emailLink = generateEmailMagicLink('user123', '[email protected]', 'secret');
// Password reset link
const resetLink = generatePasswordResetLink('user123', '[email protected]', 'secret');
一次性密码
import { generateOTP, generateTOTP, verifyTOTP } from '@bernierllc/crypto-utils';
// Simple numeric OTP
const otp = generateOTP(6); // 123456
// Time-based OTP (Google Authenticator compatible)
const secret = '48656c6c6f21deadbeef'; // Hex-encoded secret
const totp = generateTOTP(secret, {
timeStep: 30, // 30-second windows
digits: 6, // 6-digit codes
algorithm: 'sha1' // sha1 | sha256 | sha512
});
// Verify TOTP code
const isValid = verifyTOTP(userProvidedCode, secret, {
window: 1 // Allow ±1 time window (90 seconds total)
});
安保公用事业
常时比较
在比较敏感值时防止时间攻击.
import {
constantTimeCompare,
constantTimeCompareHex,
validateSecureToken
} from '@bernierllc/crypto-utils';
// Basic constant-time string comparison
const isMatch = constantTimeCompare(providedToken, expectedToken);
// Hex comparison (case-insensitive)
const hexMatch = constantTimeCompareHex('deadbeef', 'DEADBEEF'); // true
// Secure token validation with options
const isValid = validateSecureToken(providedToken, expectedToken, {
caseSensitive: false, // Case-insensitive comparison
trimWhitespace: true, // Trim whitespace
maxLength: 1000 // Maximum token length
});
密码 hash 校验
import { verifyPasswordHash } from '@bernierllc/crypto-utils';
// Custom hash function (use bcrypt, scrypt, etc. in production)
const hashPassword = (password: string) => {
return crypto.createHash('sha256').update(password + 'salt').digest('hex');
};
const isValidPassword = verifyPasswordHash(
providedPassword,
storedPasswordHash,
hashPassword
);
定时安全阵列操作
import { timingSafeIncludes } from '@bernierllc/crypto-utils';
const allowedTokens = ['token1', 'token2', 'token3'];
const isAllowed = timingSafeIncludes(allowedTokens, userToken);
完整认证流程示例
import {
generateEmailMagicLink,
verifyMagicLink,
generateAccessToken,
generateRefreshToken,
verifyJWT
} from '@bernierllc/crypto-utils';
const JWT_SECRET = process.env.JWT_SECRET!;
const MAGIC_SECRET = process.env.MAGIC_SECRET!;
// Step 1: Send magic link via email
async function sendMagicLink(email: string) {
const user = await getUserByEmail(email);
if (!user) throw new Error('User not found');
const magicLink = generateEmailMagicLink(user.id, email, MAGIC_SECRET, {
expirationMinutes: 10
});
const url = `https://app.com/auth/verify?token=${magicLink.token}`;
await sendEmail(email, 'Login to Your Account', `Click: ${url}`);
}
// Step 2: Verify magic link and issue tokens
async function verifyMagicLinkAndIssueTokens(token: string) {
const verification = verifyMagicLink(token, MAGIC_SECRET);
if (!verification.valid) {
throw new Error(`Invalid magic link: ${verification.error}`);
}
const userId = verification.payload!.userId;
const user = await getUserById(userId);
const accessToken = generateAccessToken({
sub: userId,
email: user.email,
role: user.role
}, JWT_SECRET);
const refreshToken = generateRefreshToken({
sub: userId
}, JWT_SECRET);
return { accessToken, refreshToken, user };
}
// Step 3: Validate API requests
async function authenticateRequest(authHeader: string) {
const token = authHeader.replace('Bearer ', '');
const verification = verifyJWT(token, JWT_SECRET);
if (!verification.valid) {
throw new Error(`Authentication failed: ${verification.error}`);
}
return verification.payload;
}
安保最佳做法
密钥生成
- 最小 128 位数 用于生产键的py
- 使用
generateRandomKey()最大 en - 执行碰撞检查
checkUnique
JWT 安全保卫
- 使用强大的秘密 (256+位的 en
- 短的过期时间 (15-60分钟)
- 核证所有索赔 (实例,是,是,是等)
- 仅使用 HTTPS 用于符号传输
魔法链接安全
- 短的过期时间 (登录时间5至15分钟,密码重置时间30分钟)
- 仅一次使用 - 经核实无效
- 限制费率 - 防止魔法链接垃圾邮件
- 所需HTTPS - 从不发送HTTP
常时业务
- 总是用于密码 和敏感标志
- 用于会话验证 和 API 密钥检查
- 避免字符串长度漏出 错误消息中
安全总局
- 永远不要记录机密 生产中的标志
- 使用环境变量 秘密调查
- 执行适当的密钥旋转 政策
- 在所有地方使用 HTTPS 用于符号传输
处理错误
import { generateJWT, verifyJWT, generateMagicLink } from '@bernierllc/crypto-utils';
try {
// Token generation
const token = generateJWT(payload, secret);
// Token verification
const result = verifyJWT(token, secret);
if (!result.valid) {
// Handle specific errors
if (result.error?.includes('expired')) {
console.log('Token expired, refresh required');
} else if (result.error?.includes('signature')) {
console.log('Invalid token signature');
}
}
// Magic link generation
const magicLink = generateMagicLink(userId, email, secret, {
expirationMinutes: 5
});
} catch (error) {
console.error('Crypto operation failed:', error.message);
}
类型脚本支持
包含全面类型定义的完整类型脚本支持 :
import type {
// Key generation types
KeyOptions,
GenerationResult,
ValidationResult,
KeyEncoding,
KeyAlgorithm,
// JWT types
JWTPayload,
JWTOptions,
JWTVerifyResult,
// Magic link types
MagicLinkOptions,
MagicLinkResult,
MagicLinkVerifyResult
} from '@bernierllc/crypto-utils';
// Strongly typed JWT payload
const payload: JWTPayload = {
sub: 'user123',
email: '[email protected]',
exp: Math.floor(Date.now() / 1000) + 3600
};
// Strongly typed options
const keyOptions: KeyOptions = {
length: 32,
encoding: 'hex',
validateEntropy: true
};
业绩
- 高吞吐量: > 10 000个操作/秒
- 高效编码: 优化实施
- 最小依赖性: 0 运行时间依赖性
- 内存效率: 尽可能精简业务
从 @bernierllc/ api- key- 生成器迁移
软件包保持了完全后向相容性 :
// All existing imports continue to work
import {
generateApiKey,
generateSecretKey,
generateRandomKey,
validateKeyFormat
} from '@bernierllc/crypto-utils'; // was @bernierllc/api-key-generator
许可证
(c) 2025 Bernier有限责任公司
另见
- @ bernierllc/ 拖放器 - 结构化伐木(绝不是秘密记录)
- @bernierllc/ 绝不是适应器 - 服务发现一体化