OTSkit/OTSkit-core

GitHub: OTSkit/OTSkit-core

一个零依赖、采用 TypeScript 严格模式编写的 OpenTimestamps 核心库,用于在区块链上创建和验证去中心化的文档时间戳证明。

Stars: 2 | Forks: 0

OTSkit Core

# @otskit/core [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/OTSkit/OTSkit-core/actions/workflows/ci.yml) [![CodeQL](https://static.pigsec.cn/wp-content/uploads/repos/cas/53/539e9a6bf48ad24469a4363bff3aa68124154549e26592783d3d8577f2acbbfc.svg)](https://github.com/OTSkit/OTSkit-core/actions/workflows/codeql.yml) [![npm 版本](https://img.shields.io/npm/v/@otskit/core.svg)](https://www.npmjs.com/package/@otskit/core) [![npm 下载量](https://img.shields.io/npm/dt/@otskit/core.svg)](https://www.npmjs.com/package/@otskit/core) [![TypeScript](https://img.shields.io/badge/TypeScript-6-blue.svg)](https://www.typescriptlang.org/) [![Node ≥20](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org) [![覆盖率](https://codecov.io/gh/OTSkit/OTSkit-core/branch/main/graph/badge.svg)](https://codecov.io/gh/OTSkit/OTSkit-core) [![质量门禁](https://sonarcloud.io/api/project_badges/measure?project=OTSkit_OTSkit-core&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=OTSkit_OTSkit-core) [![许可证: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) OpenTimestamps 核心库 — TypeScript,零依赖,失败即关闭(fail-closed)。 作为 [`@alexalves87/opentimestamps`](https://www.npmjs.com/package/@alexalves87/opentimestamps) 的下一代版本,我们使用 TypeScript 6 严格模式从头重写了它,它具有零外部依赖以及失败即关闭的安全姿态。 ## 什么是 OpenTimestamps? [OpenTimestamps](https://opentimestamps.org) 是一个用于去中心化时间戳证明的开放标准。它允许你通过将文档的加密哈希值锚定到 Bitcoin(或 Litecoin)区块链中,从而证明该文档在特定时间点已经存在。证明文件存储在紧凑的 `.ots` 文件中 —— 验证过程永远不需要可信的第三方参与。 ## 功能 - **零依赖** — 纯 TypeScript 实现,无 npm 供应链风险 - **设计上失败即关闭** — 严格的输入验证;默认拒绝 `ArrayBuffer`、`Buffer` 以及任何格式错误的输入 - **TypeScript 优先** — 完整的类型声明,TypeScript 6 严格模式,ESM + CJS 双构建 - **完整的协议** — 创建、序列化、反序列化、合并和验证时间戳 - **Merkle 树支持** — 在单个区块链交易中对数千个文档进行批量时间戳标记 - **纯密码学实现** — 内置 SHA1、SHA256 和 RIPEMD-160,无需原生绑定 ## 安装 ``` npm install @otskit/core ``` 需要 Node.js ≥ 20。 ## 快速开始 ### 为文件添加时间戳 ``` import { DetachedTimestampFile, OpSHA256, makePending } from '@otskit/core'; import { readFileSync, writeFileSync } from 'node:fs'; // Hash your file and wrap it in a detached timestamp const fileContent = new Uint8Array(readFileSync('document.pdf')); const dtf = DetachedTimestampFile.fromBytes(new OpSHA256(), fileContent); // Register with an OpenTimestamps calendar (pending — will be upgraded to Bitcoin) dtf.timestamp.attestations.push( makePending('https://alice.btc.calendar.opentimestamps.org'), ); // Save the .ots proof file alongside the original document writeFileSync('document.pdf.ots', dtf.serializeToBytes()); ``` ### 读取 .ots 文件 ``` import { DetachedTimestampFile } from '@otskit/core'; import { readFileSync } from 'node:fs'; const otsBytes = new Uint8Array(readFileSync('document.pdf.ots')); const dtf = DetachedTimestampFile.deserialize(otsBytes); console.log('Hash algorithm:', dtf.fileHashOp.tagName); console.log('File digest: ', Buffer.from(dtf.fileDigest()).toString('hex')); console.log('Complete: ', dtf.timestamp.isTimestampComplete()); console.log('Attestations: ', dtf.timestamp.getAttestations()); ``` ### 对比 Bitcoin 区块头进行验证 ``` import { DetachedTimestampFile, verifyAgainstBlockheader } from '@otskit/core'; import { readFileSync } from 'node:fs'; const dtf = DetachedTimestampFile.deserialize( new Uint8Array(readFileSync('document.pdf.ots')), ); // Retrieve the block header from a full node or trusted block explorer for (const { msg, attestation } of dtf.timestamp.allAttestations()) { if (attestation.kind === 'bitcoin') { verifyAgainstBlockheader(msg, blockHeader); // throws VerificationError if invalid console.log(`Verified at Bitcoin block height ${attestation.height}`); } } ``` ### 使用 Merkle 树进行批量时间戳标记 在单个区块链交易中锚定数千个文档: ``` import { DetachedTimestampFile, OpSHA256, makeMerkleTree, makePending } from '@otskit/core'; import { readFileSync, writeFileSync } from 'node:fs'; const files = ['a.pdf', 'b.pdf', 'c.pdf']; const op = new OpSHA256(); const dtfs = files.map(f => DetachedTimestampFile.fromBytes(op, new Uint8Array(readFileSync(f))), ); // One Merkle root covers all documents — one calendar call, one blockchain entry const root = makeMerkleTree(dtfs.map(d => d.timestamp)); root.attestations.push(makePending('https://alice.btc.calendar.opentimestamps.org')); // Each .ots file carries its own path to the shared root files.forEach((f, i) => writeFileSync(`${f}.ots`, dtfs[i]!.serializeToBytes())); ``` ## API 参考 ### `DetachedTimestampFile` `.ots` 证明文件的不可变包装器。 | 成员 | 描述 | |--------|-------------| | `DetachedTimestampFile.fromBytes(op, content)` | 从原始文件字节创建 | | `DetachedTimestampFile.fromHash(op, digest)` | 从预计算的摘要创建 | | `DetachedTimestampFile.deserialize(bytes)` | 解析 `.ots` 文件(仅限 `Uint8Array` — 失败即关闭) | | `.serializeToBytes()` | 序列化回 `.ots` 字节 | | `.fileDigest()` | 以 `Uint8Array` 形式返回文件的哈希值(防御性拷贝) | | `.fileHashOp` | 用于哈希文件的 `CryptOp` | | `.timestamp` | 证明树的根 `Timestamp` | ### `Timestamp` 证明树中的一个节点。每个节点持有一个摘要(`msg`)、直接证明以及指向子时间戳的操作分支。 | 成员 | 描述 | |--------|-------------| | `new Timestamp(msg)` | 创建一个新的叶节点 | | `.add(op)` | 应用一个操作并返回(或复用)子时间戳 | | `.addExisting(op, stamp)` | 交叉链接到现有时间戳(由 Merkle 内部使用) | | `.merge(other)` | 从具有相同 `msg` 的另一个时间戳中吸收证明和分支 | | `.attestations` | 直接的 `Attestation[]` — push 以向此节点添加密封 | | `.getDigest()` | `msg` 的防御性拷贝 | | `.getAttestations()` | 树中任意位置的所有证明 | | `.allAttestations()` | 树中所有的 `{ msg, attestation }` 对 | | `.isTimestampComplete()` | 如果存在 Bitcoin 或 Litecoin 证明,则返回 `true` | | `.allTips()` | 叶子摘要(没有操作的节点) | | `.equals(other)` | 深度结构相等性比较 | ### 操作 所有操作都继承自 `Op` 并且是可序列化的。二元操作(`OpAppend`、`OpPrepend`)在其构造函数中接收一个 `Uint8Array` 参数。 | 类 | 标签 | 描述 | |-------|-----|-------------| | `OpSHA256` | `0x08` | SHA-256 哈希 | | `OpSHA1` | `0x02` | SHA-1 哈希 | | `OpRIPEMD160` | `0x03` | RIPEMD-160 哈希 | | `OpAppend(suffix)` | `0xf0` | 追加字节 | | `OpPrepend(prefix)` | `0xf1` | 前置字节 | | `OpReverse` | `0xf2` | 反转字节顺序 | | `OpHexlify` | `0xf3` | 编码为 ASCII 十六进制 | ### 证明 | 函数 | 描述 | |----------|-------------| | `makePending(uri)` | 待处理日历证明 — 证明尚未升级到区块链 | | `makeBitcoin(height)` | 在区块 `height` 处的 Bitcoin 区块链证明 | | `makeLitecoin(height)` | 在区块 `height` 处的 Litecoin 区块链证明 | | `verifyAgainstBlockheader(digest, header)` | 根据 Maurkle 根验证 32 字节的摘要 — 失败时抛出 `VerificationError` | ### Merkle 树 | 函数 | 描述 | |----------|-------------| | `makeMerkleTree(timestamps)` | 从时间戳数组构建 Merkle-Mountain-Range。返回根节点。如果输入为空,则抛出 `EmptyMerkleTreeError`。 | ### 序列化上下文 用于遵循 OpenTimestamps 线级格式的底层二进制 I/O(LEB128 变长整数,长度前缀字节): | 类 | 描述 | |-------|-------------| | `StreamSerializationContext` | 写入二进制数据;调用 `.getOutput()` 获取结果 | | `StreamDeserializationContext` | 读取带有边界检查和 EOF 强制执行的二进制数据 | ### 实用工具 | 函数 | 描述 | |----------|-------------| | `hexToBytes(hex)` | 十六进制字符串 → `Uint8Array` | | `bytesToHex(bytes)` | `Uint8Array` → 小写十六进制字符串 | | `textToBytes(text)` | UTF-8 字符串 → `Uint8Array` | | `bytesToText(bytes)` | `Uint8Array` → UTF-8 字符串(遇到无效序列时抛出异常) | | `randBytes(n)` | 通过 `crypto.getRandomValues` 生成加密安全的随机字节 — 如果不可用则抛出异常 | ### 错误 所有错误类都继承自 `Error`,并按名称导出以便进行精确的 `catch` 处理。 | 类别 | 错误类 | |----------|--------------| | 反序列化 | `DeserializationError`, `BadMagicError`, `TruncatedStreamError`, `OversizedDataError`, `VaruintOverflowError`, `TrailingGarbageError`, `UnknownOperationError`, `InvalidUriError`, `UnsupportedVersionError` | | 操作 | `OpExecutionError`, `MessageTooLongError`, `ResultTooLongError` | | 验证 | `VerificationError` | | 树 | `EmptyTimestampError`, `MergeError`, `EmptyMerkleTreeError` | ## 许可证
标签:MITM代理, 自动化攻击