@keepdb/uuidv8
v1.0.11
Published
UUID v8 with expiration and HMAC signature validation - Works on Node.js, Browser, and Edge Workers
Downloads
603
Readme
@keepdb/uuidv8
带过期时间和 HMAC 签名验证的 UUID v8 实现 - 支持 Node.js、浏览器和 Edge Workers
特性
- ✅ 跨环境统一: 一套代码,Node.js 17+、浏览器、Edge Workers 全兼容
- ✅ 过期时间: 内置过期时间戳,自动验证有效期
- ✅ 场景隔离: 支持多种场景 ID(用户、会话、Token 等)
- ✅ 签名防篡改: HMAC-SHA256 签名确保数据完整性
- ✅ 零依赖: 纯 JS 实现,无外部依赖
快速开始
import { uuidv8 } from "@keepdb/uuidv8";
const result = await uuidv8(); // e.g. { uuid: "019be1e6-31c9-81bb-8011-1165a281ee18", ... }使用自定义选项生成:
import { uuidv8, ContextId } from "@keepdb/uuidv8";
const result = await uuidv8({
salt: 'my-secret-salt',
ctxId: ContextId.USER,
expiryDays: 365
});
console.log(result.uuid);
// e.g. "019be1e6-31c9-81bb-8011-1165a281ee18"
console.log(result.expiryDate.toISOString());
// e.g. "2026-01-21T18:51:58.281Z"验证 UUID:
import { validateUUID } from "@keepdb/uuidv8";
const validation = await validateUUID("019be1e6-31c9-81bb-8011-1165a281ee18", {
salt: 'my-secret-salt'
});
if (validation.valid) {
console.log('有效凭证,剩余', validation.data.remainingDays, '天');
} else {
console.log('无效:', validation.error);
}命令行工具
# 生成单个 UUID
$ npx @keepdb/uuidv8
019be1e6-31c9-81bb-8011-1165a281ee18
# 批量生成
$ npx @keepdb/uuidv8 -n 4 -c user
019be1e6-31c9-81bb-8011-1165a281ee18
019be1e6-31c9-81c2-8022-3a8b9c4d5e6f
019be1e6-31c9-81c9-8033-4b5c6d7e8f9a
019be1e6-31c9-81d6-8044-5c6d7e8f9a0b
# 验证 UUID
$ npx @keepdb/uuidv8 -s SECRET -v 019be1e6-31c9-81bb-8011-1165a281ee18
✅ 有效
场景: 0x0001
过期: 2026-01-21T18:51:58.281Z
剩余: 365 天
# JSON 输出
$ npx @keepdb/uuidv8 --json
[
{
"uuid": "019be1e6-31c9-81bb-8011-1165a281ee18",
"expiryTimestamp": 1769021518281,
"expiryDate": "2026-01-21T18:51:58.281Z",
"ctxId": 1,
"ctxHex": "0001",
"expiryDays": 365
}
]CLI 参数:
-n <count>- 生成数量-c <context>- 场景类型-s <salt>- 签名密钥-d <days>- 有效天数-v <uuid>- 验证 UUID--json/-j- JSON 格式输出-h/--help- 帮助信息
UUID 结构
本实现生成的标识符具有以下位布局:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| expiry_ts_ms |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| expiry_ts_ms | ver | ctx | sig1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var| sig2 | sig3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sig3 (cont) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+字段说明:
- 48 位
expiry_ts_ms: 过期时间的 Unix 毫秒时间戳 - 4 位
ver: 版本号,固定为1000(版本 8) - 4 位
ctx: 场景 ID(用户、会话、token 等) - 2 位
var: RFC 4122 变体,固定为10 - 80 位
sig: HMAC-SHA256 签名
场景 ID
import { ContextId } from "@keepdb/uuidv8";
ContextId.USER // 0x1 - 用户 ID
ContextId.SESSION // 0x2 - 会话 ID
ContextId.TOKEN // 0x3 - 令牌 ID
ContextId.API_KEY // 0x4 - API 密钥
ContextId.TEMP // 0x5 - 临时凭证
ContextId.SYSTEM // 0xF - 系统保留API 参考
uuidv8(options?)
生成带过期时间和签名的 UUID v8。
import { uuidv8 } from "@keepdb/uuidv8";
const result = await uuidv8({
salt: 'my-secret-salt', // 签名密钥(必填)
ctxId: ContextId.USER, // 场景 ID(默认: ContextId.USER)
expiryDays: 365 // 有效天数(默认: 365)
});返回值: { uuid, expiryTimestamp, expiryDate, createdAt, createdDate, ctxId, ctxHex, expiryDays }
validateUUID(uuid, options?)
完整验证 UUID v8(格式 + 版本 + 场景 + 签名 + 过期时间)。
import { validateUUID } from "@keepdb/uuidv8";
const validation = await validateUUID(uuid, {
salt: 'my-secret-salt', // 签名密钥
allowedContexts: [ContextId.USER], // 允许的场景 ID
checkExpiry: true // 是否检查过期时间
});返回值: { valid: boolean, error?: string, data?: {...} }
parseUUID(uuid)
解析 UUID v8 提取各部分信息。
import { parseUUID } from "@keepdb/uuidv8";
const info = parseUUID("019be1e6-31c9-81bb-8011-1165a281ee18");
// {
// expiryTimestamp: 1769021518281,
// expiryDate: Date(2026-01-21T18:51:58.281Z),
// ctxId: 1,
// ctxHex: '0001',
// version: 8,
// variant: 2,
// signature: 'bb0111165a281ee18'
// }isValidUUIDFormat(uuid)
检查字符串是否符合 UUID v8 格式。
import { isValidUUIDFormat } from "@keepdb/uuidv8";
const valid = isValidUUIDFormat("019be1e6-31c9-81bb-8011-1165a281ee18");
// truevalidateSignature(uuid, salt)
验证 HMAC 签名是否匹配。
import { validateSignature } from "@keepdb/uuidv8";
const isValid = await validateSignature(uuid, 'my-secret-salt');
// true 或 falsecalculateRemainingDays(uuid)
计算剩余有效天数。
import { calculateRemainingDays } from "@keepdb/uuidv8";
const days = calculateRemainingDays(uuid);
// "3.0"类方法
所有函数也支持通过类方法调用:
import UUIDv8 from "@keepdb/uuidv8";
const result = await UUIDv8.generate('salt', UUIDv8.ContextId.USER, 365);
const info = UUIDv8.parse(result.uuid);
const validation = await UUIDv8.validate(result.uuid, { salt: 'salt' });环境兼容性
| 环境 | 最低版本 | 状态 | | ------------------ | ---------------------- | ---------------------- | | Node.js | 17.0.0 | ✅ 全局 Web Crypto API | | 浏览器 | Chrome 37, Safari 11.1 | ✅ Web Crypto API | | Cloudflare Workers | - | ✅ Web Crypto API | | Vercel Edge | - | ✅ Web Crypto API | | Deno | 1.25+ | ✅ Web Crypto API |
安全建议
- Salt 保密: 签名密钥必须保密,建议通过环境变量配置
- HTTPS 传输: UUID 应通过 HTTPS 传输
- 定期轮换: 建议定期更换签名密钥
- 短生命周期: 敏感场景建议使用较短的有效期
许可证
MIT © 2025 Keepdb.com
