Metadata-Version: 2.4
Name: cdsm
Version: 0.1.0
Summary: 3DSM: signed .3dsm (3MF) containers with license declarations, Ed25519 provenance, geometric fingerprints and verification reports
Keywords: 3d,3dsm,3mf,provenance,licensing,watermarking,ed25519,fingerprint
Author: Shun Yang
Author-email: Shun Yang <yangshun@pkpk6.top>
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
Classifier: Typing :: Typed
Requires-Dist: cryptography>=43.0
Requires-Dist: numpy>=2.1
Requires-Dist: rfc3161ng>=2.1.3 ; extra == 'timestamp'
Requires-Python: >=3.14
Project-URL: Homepage, https://github.com/pkpk6top/3dsm
Project-URL: Repository, https://github.com/pkpk6top/3dsm
Project-URL: Issues, https://github.com/pkpk6top/3dsm/issues
Provides-Extra: timestamp
Description-Content-Type: text/markdown

# 3DSM 1.0

把许可声明、作者签名和几何指纹装进一个 `.3dsm` 文件，让已经分发出去的 3D 模型可以被独立验证与追溯。

`.3dsm` 是 3MF 的扩展容器（OPC/ZIP）：`3D/3dmodel.model` 保持任何 3MF 工具可读，`3D/share/manifest.json` 承载许可、来源、指纹与签名。

- **打包** — 写入 3MF 核心元数据与 manifest
- **签名** — manifest 规范化后 Ed25519 签名，可选 RFC 3161 时间戳
- **指纹** — 球谐幅值谱 + 簇距直方图混合（默认），可仅凭公开几何复算
- **验证** — 验签 + 指纹比对，输出结构化证据报告

> 包名是 `cdsm`，分发名与导入名一致；格式名仍是 `3dsm`，文件扩展名 `.3dsm`。

## 快速开始

需要 Python 3.14+。

```bash
uv sync
```

```python
from cdsm import DSM

DSM.keygen("author_priv.pem", "author_pub.pem")

dsm = DSM(
    license_id="CC-BY-NC-ND-4.0",
    author="Example Author",
    model_id="sha256:example0001",
    private_key="author_priv.pem",
    public_key="author_pub.pem",
)

dsm.pack("cube.model", "cube.3dsm", title="Unit Cube")
report = dsm.verify("cube.3dsm")
dsm.export("cube.3dsm", "cube.obj")

print(report["manifest_valid"], report["manifest_trust"], report["similarity_score"])
# True out_of_band 1.0
```

`pack()` 的第一个参数可以是 `Mesh`、`.model` 文件、`.obj` / `.stl` / `.ply`，或 model XML 文本。

## 许可与 policy

`license_id` 使用 SPDX 标识符。内置常用子集，未显式传参时自动推导 `derivative_policy`：

| 许可 | 衍生 | 商用 | 署名 |
| --- | --- | --- | --- |
| `CC0-1.0`、`Unlicense` | ✓ | ✓ | – |
| `MIT`、`Apache-2.0`、`BSD-3-Clause`、`MPL-2.0` | ✓ | ✓ | ✓ |
| `CC-BY-4.0`、`CC-BY-SA-4.0` | ✓ | ✓ | ✓ |
| `CC-BY-ND-4.0` | – | ✓ | ✓ |
| `CC-BY-NC-4.0`、`CC-BY-NC-SA-4.0` | ✓ | – | ✓ |
| `CC-BY-NC-ND-4.0` | – | – | ✓ |

显式传入 `derivative_allowed` / `commercial_use` / `attribution_required` 时以显式值为准。未知标识符按保守策略（禁止衍生、禁止商用、要求署名）并给出警告；`LicenseRef-*` 不生成 `license_url`。

导出到 OBJ/STL/PLY 时，政策冲突只告警、不阻断，许可与署名会写入目标格式的注释；这与规范 §7.3 的声明性定位一致，不阻断不等于授权。

```bash
uv run dsm licenses
```

完整流程（造模型 → 打包 → 验证 → 变形后复验）：

```bash
uv run python examples/demo.py
uv run pytest -q
```

## .3dsm 里有什么

```text
cube.3dsm
├── [Content_Types].xml        # OPC 内容类型
├── _rels/.rels                # StartPart 指向 /3D/3dmodel.model
├── 3D/3dmodel.model           # 3MF 核心模型 + preserve 元数据
└── 3D/share/manifest.json     # 许可、来源、指纹、签名
```

manifest 主要字段：

| 字段 | 说明 |
| --- | --- |
| `format` | 固定 `3dsm/1.0` |
| `license` / `license_url` | SPDX 标识符及其链接 |
| `derivative_policy` | `allowed`、`commercial_use`、`attribution_required`、`trace_threshold`、`lower_bound` |
| `origin` | `model_id`、`author`，可选 `title` |
| `fingerprint` | `algorithm`、`value`（`hy1:` / `sh1:` / `oh1:` + base64），可选 `watermark_id` |
| `distribution_id` | 可选，分发记录标识 |
| `signature` | `algorithm`、`value`、`public_key`，可选 `timestamp_token` |

## 验证报告

```json
{
  "report_version": "3dsm-verify/1.0",
  "manifest_valid": true,
  "manifest_trust": "out_of_band",
  "signature_reason": "ok",
  "fingerprint_algorithm": "hybrid-v1",
  "timestamp": { "status": "absent" },
  "similarity_score": 1.0,
  "trace_threshold": 0.8,
  "threshold_met": true,
  "evidence_tendency": "derivative_suspected",
  "watermark_result": "not_attempted",
  "distribution_id": null,
  "license_fields": {
    "license": "CC-BY-NC-ND-4.0",
    "derivative_allowed": false,
    "commercial_use": false,
    "attribution_required": true
  },
  "disclaimer": "This report contains evidence only and does not constitute a legal determination."
}
```

| 字段 | 取值 |
| --- | --- |
| `manifest_valid` | 签名是否通过 |
| `manifest_trust` | `out_of_band`（带外可信公钥）/ `embedded_hint`（内嵌公钥，仅提示）/ `none` |
| `fingerprint_algorithm` | 复算使用的指纹算法，取自参考 manifest |
| `timestamp` | `{"status": "absent"}`，或 RFC 3161 校验结果 |
| `similarity_score` | 与参考指纹的余弦相似度 |
| `evidence_tendency` | `derivative_suspected` / `inconclusive` / `likely_independent` |

报告只提供证据，不构成法律判定。

## 命令行

```bash
uv run dsm keygen --private author_priv.pem --public author_pub.pem
uv run dsm pack --model cube.model --key author_priv.pem --out cube.3dsm --license CC-BY-NC-ND-4.0 --author "Example Author" --model-id sha256:example0001
uv run dsm verify --candidate cube.3dsm --pub author_pub.pem --out report.json
uv run dsm inspect --path cube.3dsm
uv run dsm export --candidate cube.3dsm --out cube.obj --pub author_pub.pem
uv run dsm licenses
```

## API

| 用法 | 说明 |
| --- | --- |
| `DSM.keygen(priv, pub)` | 生成 Ed25519 密钥对 PEM |
| `dsm.pack(source, output, **overrides)` | 指纹 → manifest → 签名 → 打包，返回已签名 manifest |
| `dsm.verify(candidate, *, report_path=None, ...)` | 返回报告字典，可选落盘 |
| `dsm.inspect(path)` | 列出部件与 manifest |
| `dsm.fingerprint(source)` | 计算指纹字符串 |
| `dsm.compare(a, b)` | 两个模型的指纹相似度 |
| `dsm.export(source, output, purpose=..., is_derivative=...)` | 导出为 OBJ/STL/PLY，返回政策判定与告警 |
| `dsm.use_keys(priv, pub)` | 替换密钥，返回自身 |

## 项目结构

```text
src/cdsm/       api.py 封装 · core.py 签名与加密 · fingerprint.py 指纹
                packager.py 容器 · formats.py OBJ/STL/PLY · export.py 导出
                licenses.py 许可子集 · timestamp.py RFC 3161 · verifier.py 验证
                watermark.py 水印 provider · cli.py 命令行
docs/           规范草案（中/英）+ 技术实现指南
examples/       demo.py 端到端示例
tests/          pytest 用例
```

## 文档

- 规范草案：[中文](docs/3dsm-1.0-spec.zh.md) · [English](docs/3dsm-1.0-spec.en.md)
- [技术实现指南](docs/3dsm-1.0-implementation.zh.md)

## 许可

本仓库代码以 [Apache-2.0](LICENSE) 发布，版权与归属见 [NOTICE](NOTICE)。`.3dsm` 文件内 `manifest.license` 声明的是模型内容的许可，与本项目代码的许可相互独立。

## 已知边界

- 指纹默认 `hybrid-v1`（球谐幅值谱 + 簇距直方图），另有 `spherical-harmonics-v1` 与 `onion-hash-v1` 可选；均只依赖公开几何，安全性来自分发记录与阈值。
- 未附加时间戳时报告标注 `timestamp: absent`；RFC 3161 需要 `uv sync --extra timestamp`。
- Secure Content 只提供 AES-256-GCM / RSA-OAEP 原语，密钥释放策略由部署方决定。
- FuncMark 只在实现指南中定义接口，未实现。
- OBJ/PLY 用注释携带许可与署名；STL 只有 80 字节二进制头，信息可能被截断。
