Markdown 扩展演示
本页演示 VitePress 内置的所有 Markdown 扩展功能,每项均给出 Markdown 源码与 渲染效果对照,示例内容取自 QXJ 项目。
目录
Markdown 源码:
[[toc]]渲染效果:
自定义容器
基础容器
Markdown 源码:
::: tip
SM2 四步握手协商的会话密钥有效期为 7 天(Redis TTL)。
:::
::: info
NSP-SM Token 的 `header.alg` 值为 `"NSP-SM"`(自定义标识,实际签名算法 SM2withSM3),不是 `HS256` 或 `RS256`。
:::
::: warning
生产环境必须设置 `QXJ_KEY_ENC_KEY` 环境变量;未设置时生产环境直接启动失败。
:::
::: danger
不要在日志中打印完整的 Access Token、Refresh Token 或会话密钥。
:::2
3
4
5
6
7
8
9
10
11
12
13
14
15
渲染效果:
提示
SM2 四步握手协商的会话密钥有效期为 7 天(Redis TTL)。
信息
NSP-SM Token 的 header.alg 值为 "NSP-SM"(自定义标识,实际签名算法 SM2withSM3),不是 HS256 或 RS256。
警告
生产环境必须设置 QXJ_KEY_ENC_KEY 环境变量;未设置时生产环境直接启动失败。
危险
不要在日志中打印完整的 Access Token、Refresh Token 或会话密钥。
自定义标题
Markdown 源码:
::: tip SM2 握手提示
INIT 帧总长度 280 字节 = 64B 帧头 + 216B 数据域。
:::2
3
渲染效果:
SM2 握手提示
INIT 帧总长度 280 字节 = 64B 帧头 + 216B 数据域。
details 折叠
Markdown 源码:
::: details 64B 帧头偏移速查表(点击展开)
| 偏移 | 大小 | 字段 |
|------|------|------|
| 0 | 1 | version |
| 8 | 36 | sender_id |
:::2
3
4
5
6
7
8
渲染效果:
64B 帧头偏移速查表(点击展开)
| 偏移 | 大小 | 字段 | 说明 |
|---|---|---|---|
| 0 | 1 | version | 0x01 |
| 1 | 1 | main_cmd | 0x00 协商 / 0x01 报警 / 0x02 加密完保 |
| 2 | 2 | sub_cmd | 最高位 0x8000=下行 |
| 4 | 2 | total_len | 数据域长度 |
| 6 | 2 | seq | 序列号 |
| 8 | 36 | sender_id | ASCII,不足补 0x00 |
| 44 | 1 | enc_auth | 高 4 位加密 / 低 4 位认证 |
| 45 | 16 | iv | 握手帧全零 |
| 61 | 3 | reserved | 保留 |
容器嵌套
Markdown 源码:
::: tip 嵌套容器示例
外层是 tip 容器。
::: warning 内层 warning
可以嵌套不同类型的容器。
:::
嵌套结束。
:::2
3
4
5
6
7
8
9
渲染效果:
嵌套容器示例
外层是 tip 容器。
内层 warning
可以嵌套不同类型的容器。
嵌套结束。 :::
GitHub-flavored Alerts
Markdown 源码:
> [!NOTE]
> NSP-SM Token 基于 SimpleJWT 框架扩展 SM2withSM3 非对称签名,非默认 HS256。
> [!IMPORTANT]
> `enc_auth` 字段在 `iv` 之前,偏移 44。
> [!CAUTION]
> 内层 HMAC 不匹配时令牌校验不通过。
> [!TIP]
> 开发环境可用 `python -m tools.setup inspect` 查看本地密钥详情。2
3
4
5
6
7
8
9
10
11
渲染效果:
NOTE
NSP-SM Token 基于 SimpleJWT 框架扩展 SM2withSM3 非对称签名,非默认 HS256。
IMPORTANT
enc_auth 字段在 iv 之前,偏移 44。握手帧 enc_auth = 0x00,加密帧 enc_auth = 0x40。
CAUTION
内层 HMAC 不匹配时令牌校验不通过。
TIP
开发环境可用 python -m tools.setup inspect 查看本地密钥详情。
代码行高亮
在代码块语言后加 {行号} 高亮指定行,支持逗号列举与区间。
Markdown 源码:
```ts{1,3-5,9}
// QxjFrameUtil.ets 帧头常量
const FRAME_HEADER_LEN = 64
const ENC_AUTH_SM4_GCM = 0x40
const MAIN_CMD_SECURE = 0x02
const SUB_CMD_UP = 0x0001
const SUB_CMD_DOWN = 0x8002
function encryptFrame(key: string, iv: string, data: string): string {
const header = buildFrameHeader()
const ciphertext = sm4GcmEncrypt(key, iv, data)
return header + ciphertext
}
```2
3
4
5
6
7
8
9
10
11
12
13
14
渲染效果:
// QxjFrameUtil.ets 帧头常量
const FRAME_HEADER_LEN = 64
const ENC_AUTH_SM4_GCM = 0x40
const MAIN_CMD_SECURE = 0x02
const SUB_CMD_UP = 0x0001
const SUB_CMD_DOWN = 0x8002
function encryptFrame(key: string, iv: string, data: string): string {
const header = buildFrameHeader()
const ciphertext = sm4GcmEncrypt(key, iv, data)
return header + ciphertext
}2
3
4
5
6
7
8
9
10
11
12
代码差异对比
语言后加 diff,用 + / - 标记增删行。
Markdown 源码:
```ts diff
- // 旧文档口径(错误)
- const SUB_CMD_LEN = 1
- const TOTAL_LEN_OFFSET = 3
+ // 正确口径(packet_parser.py 实测,64B 帧头)
+ const SUB_CMD_LEN = 2 // 偏移 2
+ const TOTAL_LEN_OFFSET = 4 // 2 字节
+ const ENC_AUTH_OFFSET = 44 // enc_auth 在 iv 之前
```2
3
4
5
6
7
8
9
渲染效果:
- // 旧文档口径(错误)
- const SUB_CMD_LEN = 1
- const TOTAL_LEN_OFFSET = 3
+ // 正确口径(packet_parser.py 实测,64B 帧头)
+ const SUB_CMD_LEN = 2 // 偏移 2
+ const TOTAL_LEN_OFFSET = 4 // 2 字节
+ const ENC_AUTH_OFFSET = 44 // enc_auth 在 iv 之前2
3
4
5
6
7
代码错误、警告与聚焦标记
行末加 // [!code error]、// [!code warning] 显示红 / 黄背景; // [!code highlight] 行内高亮,// [!code focus] 整行聚焦(其余行变淡)。
Markdown 源码:
```py
def verify_token(token, public_key):
if not sm2_verify(token, public_key):
raise AuthenticationFailed("外层 SM2 验签失败")
```
```ts
const sessionKey = deriveSessionKey(rA, rB, idA, idB)
const iv = crypto.randomBytes(12)
```2
3
4
5
6
7
8
9
10
渲染效果:
def verify_token(token, public_key):
if not sm2_verify(token, public_key):
raise AuthenticationFailed("外层 SM2 验签失败") 2
3
const sessionKey = deriveSessionKey(rA, rB, idA, idB)
const iv = crypto.randomBytes(12) 2
任务列表
Markdown 源码:
- [x] SM2 四步握手协议(INIT/RESP/ACK/TOKEN)
- [x] SM4-GCM 加密帧封装与解析
- [x] 图像数字水印(PSNR 38.10 dB)
- [ ] 密钥更新与年审
- [ ] CI/CD 流水线(手动部署)2
3
4
5
渲染效果:
- SM2 四步握手协议(INIT/RESP/ACK/TOKEN)
- SM4-GCM 加密帧封装与解析
- 图像数字水印(PSNR 38.10 dB)
- 密钥更新与年审
- CI/CD 流水线(手动部署)
脚注
Markdown 源码:
设备访问 MCS 时需携带 NSP-SM Token[^nsp],业务后端本地完成
SM2 验签与内层 HMAC 校验[^hmac]。
[^nsp]: **NSP-SM Token**:SM2withSM3 签名的联合令牌,payload 含用户与设备信息。
[^hmac]: **内层 HMAC**:基于 Redis 中的会话密钥计算,校验令牌与当前会话绑定。2
3
4
5
渲染效果:
设备访问 MCS 时需携带 NSP-SM Token[1],业务后端本地完成 SM2 验签与内层 HMAC 校验[2]。
Emoji 简写
Markdown 源码:
:tada: 项目已通过安全审计 :100:
常用:`:rocket:` :rocket:、`:lock:` :lock:、`:white_check_mark:` :white_check_mark:2
3
渲染效果:
🎉 项目已通过安全审计 💯
常用::rocket: 🚀、:lock: 🔒、:white_check_mark: ✅
代码组
用 ::: code-group 组织多语言同功能代码,标签写在代码块语言后的 [] 中。
Markdown 源码:
::: code-group
```python [Python SDK]
from qxj_backend_sdk import verify_access_token
device_id, expire_time, code = verify_access_token(
token, public_key, redis_client
)
```
```typescript [JS 前端 SDK]
import { sm4GcmEncrypt } from 'qxj-frontend-sdk'
const encrypted = sm4GcmEncrypt(key, iv, plaintext)
```
:::2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
渲染效果:
from qxj_backend_sdk import verify_access_token
device_id, expire_time, code = verify_access_token(
token, public_key, redis_client
)
# code: 0=通过 1=仅外层 -3=SM2失败 -6=HMAC失败2
3
4
5
6
import { sm4GcmEncrypt, sm4GcmDecrypt } from 'qxj-frontend-sdk'
// key 必须 32 字节(64 hex),iv 任意非空
const encrypted = sm4GcmEncrypt(key, iv, plaintext)
const decrypted = sm4GcmDecrypt(key, iv, encrypted)2
3
4
5
import { QxjSessionCrypto } from '@nsp/qxj-sdk'
// 帧头 64B + SM4-GCM 密文
const frame = QxjSessionCrypto.encryptFrame(sessionKey, ivHex, dataHex)
const plain = QxjSessionCrypto.decryptFrame(sessionKey, ivHex, frameHex)2
3
4
5
数学公式
行内公式用单个 $,块级公式用 $$。
Markdown 源码:
$$
\text{PSNR} = 10 \log_{10}\left(\frac{\text{MAX}^2}{\text{MSE}}\right)
$$
SM2 密钥交换参数:$\lambda = \frac{n}{2} \approx 128\text{ bit}$2
3
4
5
渲染效果:
SM2 密钥交换参数:
Mermaid 流程图
Markdown 源码:
```mermaid
sequenceDiagram
participant D as 设备
participant S as 服务器
participant R as Redis
D->>S: INIT 帧
S->>R: 缓存会话密钥
S->>D: RESP 帧
D->>S: ACK 帧
S->>D: TOKEN 帧
```2
3
4
5
6
7
8
9
10
11
12
渲染效果: