Show HN: Let's Seal —— 用于文档签名的 Let's Encrypt,免费且可自托管
Show HN: Let's Seal – Let's Encrypt for document signing, free and self-hosted

原始链接: https://github.com/letsseal/letsseal

**SEAL** 是一项用于验证任何文件真实性的开源标准。正如 Let’s Encrypt 彻底改变了网络安全一样,Let’s Seal 提供了一种由基金会运营的免费公共基础设施,使付费文档盖章服务成为过去。 SEAL 证明提供三项加密保障: 1. **完整性:** 确保文件自盖章后未被篡改。 2. **时间戳:** 通过 OpenTimestamps 将文件锚定在比特币区块链上,证明文件存在于特定时间。 3. **签发者:** 将印章与经过验证的域名身份绑定。 所有记录均保存在一个仅支持追加的透明度日志(RFC 6962)中,确保记录永久、防篡改且可供任何人审计。 用户可通过托管的 Web 应用程序、命令行工具 (sealbot) 或 API 对文件进行盖章,所有这些均为免费,且不收取任何单份文档费用。验证过程始终免费,无需账户,且支持离线操作。由于 SEAL 使用原生格式(例如 PDF 使用 PAdES,媒体文件使用 C2PA),因此盖章后的文件保持标准且可移植。作为一个以公共利益为导向而非初创公司的项目,从标准本身到软件开发工具包 (SDK) 的整个技术栈均开源 (Apache-2.0),确保真实性验证是一项可访问的基础设施,而非付费服务。

**Let’s Seal** 是一个全新的开源项目,旨在通过提供免费、可自托管的替代方案,取代 DocuSign 或 Adobe 等专有服务,从而实现文档签署的去中心化。正如 Let’s Encrypt 为 TLS 所做的那样,该项目致力于消除数字签名和验证领域中“付费才能使用”的门槛。 该平台利用三重验证方法来确保文件完整性: 1. **证书颁发机构 (CA) 签名**:连接至公共根证书。 2. **RFC 6962 透明度日志**:用于审计。 3. **比特币区块链时间戳**:通过 OpenTimestamps 提供不可篡改的存在证明。 用户可以通过免费的 Web 应用访问该系统,自行托管,或使用“sealbot”命令行工具将其集成到 CI/CD 工作流中。尽管该项目因其普及数字信任的潜力而受到赞誉,但 Hacker News 上的社区反馈也提出了担忧,主要集中在缺乏正式标准化(无 RFC/ISO 支持)、需要更强大的电子签名功能(如模板、高级字段),以及在保守市场中建立法律和机构信任所面临的挑战。目前,该项目仍处于通过开放标准实现信任商品化的早期尝试阶段。
相关文章

原文

SEAL is the open standard for proving any file is real. One sealed artifact, one way to check it, verifiable by anyone, forever. Seal with any conforming tool, and anyone can verify it with any other.

Let's Seal created that standard, SEAL, Sealed Evidence Anchored to a Ledger, and runs the free network and reference implementation that issues and verifies it. The standard is the backbone. Everything in this repository is built on it, and given away.

It is the Let's Encrypt of document proof. Let's Encrypt made paid TLS certificates obsolete. Let's Seal does the same for paid document seals, and like Let's Encrypt it is free, open, and run as a public-benefit project of a foundation, not a startup.

Authenticity is infrastructure. It shouldn't be for rent.

Three ways to seal, all free:

  • The hosted web app, app.letsseal.org. Free for anyone, in the browser, nothing to install. Seal a file, send documents out for signature (remote, in person, or with no email at all), and issue branded certificates and credentials.
  • The command line and API. sealbot for the terminal, plus a REST API and SDKs to build sealing into your own systems.
  • Self-hosted. Run the whole engine yourself, under your own certificate authority.

Verifying is always free and never needs an account, at verify.letsseal.org or offline on your own machine.

  • Free forever. No per-document fees, no paid seal.
  • Open source (Apache-2.0). The engine, the SDKs, and the standard itself.

A SEAL proof establishes three things cryptographically, and states its boundary plainly:

  • Unaltered. The file has not changed by a single byte since it was sealed. Change one byte and the signature breaks.
  • Time. It existed by a certain date, anchored to Bitcoin through OpenTimestamps, with no trust in us.
  • Issuer. It was sealed by a specific certificate. Where an organisation has proven control of a domain, the seal carries that domain as a machine-checkable identity.

Every seal is also written to a public, append only transparency log (RFC 6962) with a Bitcoin anchored root, so the record of what was sealed is itself tamper evident and anyone can audit it.

That is the whole guarantee, complete and permanent. A seal proves integrity, time, and the issuing certificate. It is not notarisation, and it does not assert a person's real world identity. The identity feature binds an email that a provider verified at seal time, and the honest term for it is a provider verified email, which is exactly what it delivers.

One standard, every kind of file, each in its own native format so any standard validator can check it. No bespoke tooling for the reader, and no dependency on Let's Seal to verify.

File Seal form How it verifies
PDF PAdES / X.509 signature embedded in the file Any standard PAdES validator, or the reference verifier here
Image, video, audio C2PA (Content Credentials) manifest embedded in the media Any C2PA reader
XML Enveloped W3C XML-DSig signature Any XML-DSig validator
Email S/MIME multipart/signed (RFC 8551) openssl smime -verify
Any other file Detached CAdES / CMS .sig over the file's SHA-256 openssl cms -verify; the file's bytes never leave your machine
Software artifact, container image Signature plus in-toto / DSSE attestation (SBOM, SLSA provenance) The standard open artifact-signing tools your pipeline already runs

The seal is native to each format, so a sealed PDF is still a normal PDF that opens anywhere, a sealed image still shows everywhere, and a signed artifact still installs as usual. The proof rides along inside.

Seal and verify from the command line:

sealbot sealing and verifying a document on the command line

The free public verification portal, verify.letsseal.org:

The Let's Seal verification portal

A public proof page: the plain-English verdict anyone can open, with the evidence behind it. Subject and signer details stay private until you upload the file:

A Let's Seal proof page

The hosted app at app.letsseal.org does the rest: seal files, send documents out for signature (remote, in person, or with no email at all), and issue branded certificates and credentials.

Verify any sealed document, free and in the open, at verify.letsseal.org, or run the reference verifier yourself:

python spec/verify.py sealed.pdf sealed.pdf.ots

Seal a file through the hosted API with an organisation key:

curl -X POST https://app.letsseal.org/api/v1/seal \
  -H "Authorization: Bearer $LETSSEAL_KEY" \
  -F [email protected]

Or from the command line:

sealbot seal contract.pdf          # seal a PDF or any file
sealbot verify contract.sealed.pdf # verify a seal, offline

SDKs for Python and TypeScript, plus the OpenAPI schema, live in sdk/.

Open a sealed file's proof page, or run the verifier, and you get a plain verdict backed by evidence anyone can reproduce:

Authentic and unaltered

  Document      contract.pdf
  SHA-256       9f2c1a…e7b4     (matches the sealed bytes, exactly)
  Issuer        Acme Solicitors LLP
                Issuer verified, controls acme.example  (dNSName in the cert)
  Sealed        2026-07-14 11:42 UTC
  Time anchor   Bitcoin block #812,043   (via OpenTimestamps)
  Transparency  Entry #48,120 in the public log, inclusion proof checks out

Verdict rule: Authentic = valid and intact and trusted.
A valid signature that does not chain to the published root is
reported as unrecognised, never as authentic.

The verdict is deliberately strict. A cryptographically valid signature from a certificate that does not chain to the pinned root is a forgery vector, and it is reported as unrecognised, never as a pass.

How a seal is made and checked

The life of a seal: made once, evidenced and anchored to the public ledger, served back, and checkable by anyone, forever.

The life of a seal: you seal a file, it is evidenced and anchored to the public ledger, served back, and anyone can verify it forever. Authentic = valid and intact and trusted.

Two checks, both independent of us. A seal carries everything needed to check it, so pin the published root once and then verify offline, anywhere, forever.

  • Root fingerprint (SHA-256): 02:68:6D:EE:20:67:31:C4:59:C1:7A:9F:58:36:7B:0B:0B:BA:5D:24:C6:85:D8:6D:1F:74:49:86:2D:C0:FE:BE, subject CN=Let's Seal Root CA, O=Let's Seal, C=GB. Download it at letsseal.org/api/root-ca.
  • PDF: any standard PAdES validator with the root pinned, or python spec/verify.py sealed.pdf sealed.pdf.ots.
  • Email and detached: openssl smime -verify -in message.eml -CAfile letsseal-root.crt · openssl cms -verify -inform DER -in file.sig -content file -binary -CAfile letsseal-root.crt.
  • Software and SBOM: the standard open artifact-signing tools verify the signature and attestation against the published root, reproducible on any machine.
  • Time: ots verify sealed.pdf.ots against Bitcoin.
  • Transparency log: fetch an inclusion proof at /api/log/proof?sha256=<hex> and check it against the signed tree head at /api/log/sth (RFC 6962). Consistency proofs at /api/log/consistency prove the log is append only.

The public transparency log

Every seal is written to an append only Merkle log (RFC 6962), the same structure browsers rely on for Certificate Transparency. The log's root is signed and itself anchored to Bitcoin, so:

  • anyone can prove a given seal is included in the log (an inclusion proof),
  • anyone can prove the log has never been rewritten (a consistency proof),
  • and the whole thing can be audited without trusting the operator.

It is the impersonation audit trail: if a certificate ever sealed something under a name it shouldn't have, the evidence is public and permanent.

A seal always proves which certificate signed it. On top of that, an organisation can prove control of a domain (DNS record or a message to a controller address), and that domain is then bound into the signing certificate itself as a dNSName, so an off-platform verifier reads the identity straight from the certificate.

  • Organisations that have not verified a domain are shown as self asserted, never as verified.
  • A verified issuer's badge is the domain it controls, which is globally unique and cannot collide.
  • Abuse can be reported publicly, and an impersonating issuer can be suspended, which stops its keys and drops its verified badge.

This is domain control as identity, the same model the web took for TLS. It proves who controls the seal, not a person's legal identity, and it says so plainly.

Open to verify. Open to implement. Impossible to lock up.

SEAL is a published specification anyone can build on, see SPEC.md and letsseal.org/standard. The goal is one interoperable way to seal and verify any file, not a product to lock into. A SEAL proof is integrity, time, transparency, and optional verified-email attribution in a single self-contained artifact.

The signing service, the SDKs, and the reference verifier in this repository are the reference implementation. Anyone else is free to write their own, and a proof made by one implementation verifies under any other.

The standard fits any file and any sector. Worked guides for the common ones, each with step-by-step instructions and live proofs:

See them all at letsseal.org/use-cases.

Let's Seal architecture: issuance (root CA to intermediate CA to the localhost signing service), delivery (the web app anchors each seal to the public ledger, appends it to the transparency log, and publishes proof pages), and verification by anyone with no Let's Seal server.

The engine is fully self hostable and carries no hosted only code paths. A single-user install runs the identical code the hosted service runs.

Run the whole thing yourself, under your own certificate authority.

git clone https://github.com/letsseal/letsseal.git && cd letsseal

# 1. Certificate authority (see ca/)
./ca/setup-ca.sh init

# 2. Signing service (holds the intermediate key; bind to localhost)
cd signing-service && python -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt && uvicorn main:app --port 8081

# 3. Web app: dashboard, hosted API, verification portal, site
cd ../web && npm install && cp .env.example .env   # fill in the values
npx prisma migrate deploy && npm run dev            # http://localhost:3000

You can swap in a paid AATL or eIDAS .p12 later with zero code changes, if you want a reader's automatic green check for verifiers outside your own portal. The cryptographic guarantee is identical either way. Your verification portal is the trust anchor.

REST API (hosted or self-hosted), authenticated with an organisation API key:

POST /api/v1/seal            seal a PDF (PAdES)
POST /api/v1/seal/c2pa       seal an image, video, or audio file (C2PA)
POST /api/v1/seal/xml        seal XML (XML-DSig)
POST /api/v1/seal/smime      seal an email message (S/MIME)
POST /api/v1/seal/detached   seal any file by digest (detached CAdES)
POST /api/v1/seal/blob       seal a software artifact
POST /api/v1/seal/identity   seal with a provider-verified email
POST /api/v1/attest          attach an SBOM / SLSA attestation
POST /api/v1/anchor          anchor a hash to Bitcoin
POST /api/v1/verify          verify a seal  (public, no key)
GET  /api/v1/whoami          check a key's organisation

Digest-only endpoints (/seal/detached, /seal/blob) never receive the file's bytes, only its SHA-256.

CLI: sealbot seal, sealbot verify, sealbot issue, sealbot anchor, sealbot watch. Install with npm i -g sealbot (or run npx sealbot); a self-contained Rust build lives in cli-rs/.

SDKs: hand-written clients for Python (sdk/python) and TypeScript (sdk/ts), plus the OpenAPI schema (sdk/openapi.json). Generate a client for any other language with sdk/generate.sh.

CI: seal build artifacts in a pipeline with the GitHub Action in ci/.

Path What it is
ca/ Certificate authority as code (root and intermediate issuance)
signing-service/ FastAPI signing service (holds the intermediate key)
web/ Next.js app: dashboard, hosted API, verification portal, site
spec/ The SEAL specification and reference verifier
sdk/ Python and TypeScript SDKs, the OpenAPI schema, and generate.sh
cli/, cli-rs/ The sealbot command line tool (Node and Rust)
ci/ A GitHub Action for sealing artifacts in CI

Authenticity is infrastructure. It shouldn't be for rent. Proving a file is real is a public good, like a padlock in a browser bar, and it should be free, open, and owned by everyone who relies on it. Let's Seal is run as a public-benefit project of a foundation, not a startup, so the standard can never be pulled back behind a paywall.

Apache-2.0, see LICENSE and NOTICE. The SEAL specification is free to implement.

Created and maintained by nsokin. Let's Seal is a project of Experimental Open Works.

联系我们 contact @ memedata.com