86 lines
5.0 KiB
SQL
86 lines
5.0 KiB
SQL
-- ============================================================
|
||
-- 安全设备 Demo - 数据库初始化脚本
|
||
-- 库名: secure_device (与 application.properties 中配置一致)
|
||
-- 说明: 存储照片元数据、设备、用户
|
||
-- 密文本身落盘于 uploads/ 目录
|
||
-- 服务端永远不存明文照片和明文 DEK
|
||
-- ============================================================
|
||
|
||
-- 1. 创建数据库(如已存在可跳过)
|
||
CREATE DATABASE IF NOT EXISTS `secure_device`
|
||
DEFAULT CHARACTER SET utf8mb4
|
||
DEFAULT COLLATE utf8mb4_general_ci;
|
||
|
||
USE `secure_device`;
|
||
|
||
-- 2. 加密照片表(对应 EncryptedPhoto 实体)
|
||
CREATE TABLE IF NOT EXISTS `encrypted_photo` (
|
||
`photo_id` VARCHAR(64) NOT NULL COMMENT '照片唯一 ID (PK)',
|
||
`device_id` VARCHAR(64) DEFAULT NULL COMMENT '来源设备 ID',
|
||
`user_id` VARCHAR(64) DEFAULT NULL COMMENT '所属用户 ID',
|
||
`file_path` VARCHAR(512) DEFAULT NULL COMMENT '密文文件落盘路径',
|
||
`iv_base64` VARCHAR(256) DEFAULT NULL COMMENT 'GCM IV (Base64)',
|
||
`encrypted_dek_base64` VARCHAR(1024) DEFAULT NULL COMMENT 'DEK 被 UK 加密后的密文 (Base64)',
|
||
`metadata_signature` VARCHAR(1024) DEFAULT NULL COMMENT '设备私钥签名 (Base64)',
|
||
`upload_time` BIGINT DEFAULT NULL COMMENT '上传时间戳 (ms)',
|
||
PRIMARY KEY (`photo_id`),
|
||
KEY `idx_user_id` (`user_id`),
|
||
KEY `idx_device_id` (`device_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='加密照片元数据表';
|
||
|
||
-- 3. 设备表(对应 Device 实体)
|
||
CREATE TABLE IF NOT EXISTS `device` (
|
||
`device_id` VARCHAR(64) NOT NULL COMMENT '设备唯一 ID (UUID, PK)',
|
||
`sn` VARCHAR(64) NOT NULL COMMENT '设备序列号 (唯一)',
|
||
`user_id` VARCHAR(64) DEFAULT NULL COMMENT '绑定的用户 ID',
|
||
`public_key_base64` TEXT DEFAULT NULL COMMENT '设备 TEE 公钥 (Base64)',
|
||
`bind_time` BIGINT DEFAULT NULL COMMENT '绑定时间戳 (ms)',
|
||
`last_recovery_time` BIGINT DEFAULT NULL COMMENT '最近一次恢复时间戳 (ms)',
|
||
`active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否激活 (1 激活 / 0 停用)',
|
||
PRIMARY KEY (`device_id`),
|
||
KEY `idx_device_sn` (`sn`),
|
||
KEY `idx_device_user` (`user_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='设备注册与绑定状态表(一个 SN 可有多条历史记录,仅一条 active)';
|
||
|
||
-- 4. 用户表(对应 User 实体)
|
||
CREATE TABLE IF NOT EXISTS `app_user` (
|
||
`user_id` VARCHAR(64) NOT NULL COMMENT '用户 ID (PK)',
|
||
`phone` VARCHAR(32) DEFAULT NULL COMMENT '手机号(用于短信验证)',
|
||
`uk_encrypted_base64` TEXT DEFAULT NULL COMMENT '用户主密钥 UK(经 SMK-AES-256-GCM 信封加密,格式 ivBase64:ciphertextBase64,非明文)',
|
||
`password` VARCHAR(128) DEFAULT NULL COMMENT '登录密码 (BCrypt 哈希,60 字符,绝不明文)',
|
||
`phone_verified` VARCHAR(8) DEFAULT NULL COMMENT '手机号是否已验证',
|
||
PRIMARY KEY (`user_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户与主密钥表';
|
||
|
||
-- ============================================================
|
||
-- 已有数据库迁移(仅当旧库的 device 表带 SN 唯一索引时手动执行)
|
||
-- 说明:早期版本 device.sn 建为 UNIQUE 索引,导致「恢复出厂重新注册」时
|
||
-- 报 Duplicate entry。现将 SN 改为普通索引(一个 SN 可有多条历史设备记录,
|
||
-- 仅一条 active)。spring.jpa.hibernate.ddl-auto=update 不会自动删除已存在
|
||
-- 的唯一索引,故需手动执行下面两句:
|
||
-- ============================================================
|
||
-- ALTER TABLE `device` DROP INDEX `idx_device_sn`;
|
||
-- ALTER TABLE `device` ADD INDEX `idx_device_sn` (`sn`);
|
||
|
||
-- ============================================================
|
||
-- 迁移:P0-1 修复(UK 明文落库 -> SMK 信封加密)
|
||
-- ============================================================
|
||
-- 列结构无需变更(uk_encrypted_base64 本就是 TEXT)。
|
||
-- 已有旧数据(明文 UK,Base64 且不含冒号)需重新用 SMK 包裹。
|
||
-- 纯 SQL 无法完成 AES-256-GCM(密钥来自环境变量 APP_MASTER_KEY),
|
||
-- 因此由应用侧一次性 Runner 完成:
|
||
--
|
||
-- 设置环境变量后启动应用一次:
|
||
-- export APP_MASTER_KEY=<Base64 的 32 字节>
|
||
-- export APP_RUN_MIGRATION=true
|
||
-- # 启动 Spring Boot,Runner 自动把明文 UK 重新包裹
|
||
-- # 成功后关闭:unset APP_RUN_MIGRATION
|
||
--
|
||
-- 若数据库为演示数据、可整体重建,则无需迁移,直接:
|
||
-- TRUNCATE TABLE `app_user`;
|
||
-- TRUNCATE TABLE `encrypted_photo`;
|
||
-- TRUNCATE TABLE `device`;
|
||
-- 然后重新走注册流程即可(新账号 UK 默认即用 SMK 加密)。
|
||
-- 注:早期版本存在 user_photo 关联表(已废弃),照片归属统一由 encrypted_photo.user_id 承担。
|
||
-- ============================================================
|