npm package: @keepdb/uuidv8
Description: UUID v8 with expiration and HMAC signature validation - Works on Node.js, Browser, and Edge Workers
Author: benz
Latest version: 1.0.11

# @keepdb/uuidv8

[![npm](https://img.shields.io/npm/v/@keepdb/uuidv8)](https://www.npmjs.com/package/@keepdb/uuidv8)
[![License](https://img.shields.io/npm/l/@keepdb/uuidv8)](https://github.com/keepdb/uuidv8/blob/main/LICENSE)

> 带过期时间和 HMAC 签名验证的 UUID v8 实现 - 支持 Node.js、浏览器和 Edge Workers

## 特性

- ✅ **跨环境统一**: 一套代码，Node.js 17+、浏览器、Edge Workers 全兼容
- ✅ **过期时间**: 内置过期时间戳，自动验证有效期
- ✅ **场景隔离**: 支持多种场景 ID（用户、会话、Token 等）
- ✅ **签名防篡改**: HMAC-SHA256 签名确保数据完整性
- ✅ **零依赖**: 纯 JS 实现，无外部依赖

## 快速开始

```javascript
import { uuidv8 } from "@keepdb/uuidv8";

const result = await uuidv8(); // e.g. { uuid: "019be1e6-31c9-81bb-8011-1165a281ee18", ... }
```

使用自定义选项生成：

```javascript
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：

```javascript
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);
}
```

## 命令行工具

```bash
# 生成单个 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 结构

本实现生成的标识符具有以下位布局：

```text
 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

```javascript
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。

```javascript
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（格式 + 版本 + 场景 + 签名 + 过期时间）。

```javascript
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 提取各部分信息。

```javascript
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 格式。

```javascript
import { isValidUUIDFormat } from "@keepdb/uuidv8";

const valid = isValidUUIDFormat("019be1e6-31c9-81bb-8011-1165a281ee18");
// true
```

### `validateSignature(uuid, salt)`

验证 HMAC 签名是否匹配。

```javascript
import { validateSignature } from "@keepdb/uuidv8";

const isValid = await validateSignature(uuid, 'my-secret-salt');
// true 或 false
```

### `calculateRemainingDays(uuid)`

计算剩余有效天数。

```javascript
import { calculateRemainingDays } from "@keepdb/uuidv8";

const days = calculateRemainingDays(uuid);
// "3.0"
```

### 类方法

所有函数也支持通过类方法调用：

```javascript
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      |

## 安全建议

1. **Salt 保密**: 签名密钥必须保密，建议通过环境变量配置
2. **HTTPS 传输**: UUID 应通过 HTTPS 传输
3. **定期轮换**: 建议定期更换签名密钥
4. **短生命周期**: 敏感场景建议使用较短的有效期

## 许可证

MIT © 2025 Keepdb.com