Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ make w3c # serve the W3C draft at http://localhost:8000
make w3c-check # render the W3C draft and fail on ReSpec diagnostics
```

`make check` needs Bash, Git, grep, jq, and Node.js 22 or newer. The other
`make check` needs Bash, Git, grep, and Node.js 22 or newer. The other
targets list their tool requirements below.

## Choose the document you need
Expand Down Expand Up @@ -77,16 +77,17 @@ Then run `make paper`. The PDF is ignored by Git.
The W3C draft uses ReSpec. Run `make w3c`, open <http://localhost:8000>, and
inspect the rendered draft. `make w3c-check` uses pinned ReSpec 37.3.5 and
writes its temporary snapshot under `$TMPDIR` when set, then `RUNNER_TEMP` or
`/var/tmp`. It needs Node.js 24 or newer and Chrome or Chromium.
`/var/tmp`. It needs Node.js 22 or newer and Chrome or Chromium.

## Understand implementation status

The drafts define the target protocol. The reference repositories implement
the stable `v0.2.2` canonicalization profile and the current end-to-end flow.
The newest draft rules for parser-profile rejection, U+0040 attribute-record
escaping, complete RFC 8785 processing, resource ceilings, and native browser
DOM integration still require downstream implementation work. The review
documents identify each remaining gap.
The newest draft rules still require downstream implementation work. These
include the v1 JCS signing object and location scope, safe signed URLs,
parser-profile rejection, U+0040 escaping, complete RFC 8785 processing,
resource ceilings, and the native browser lifecycle. The review documents
identify each remaining gap.

Current prototype repositories:

Expand Down
2 changes: 2 additions & 0 deletions ietf-draft/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ processing model lives in `../w3c-cg/`.
- `vectors/attribute-records.json` — signed-attribute framing and escaping cases.
- `vectors/nested-section.json` — nested signed-section boundary behavior.
- `vectors/origin-serialization.json` — tuple-origin serialization and rejection cases.
- `vectors/signing-profile-v1.json`: the versioned signing object, URL scope,
timestamp, safe-URL, key, and Ed25519 signature vector.
- `README.md` — this file.

## Before submitting
Expand Down
683 changes: 473 additions & 210 deletions ietf-draft/draft-grey-htmltrust-00.html

Large diffs are not rendered by default.

550 changes: 375 additions & 175 deletions ietf-draft/draft-grey-htmltrust-00.md

Large diffs are not rendered by default.

1,440 changes: 804 additions & 636 deletions ietf-draft/draft-grey-htmltrust-00.txt

Large diffs are not rendered by default.

1,964 changes: 1,124 additions & 840 deletions ietf-draft/draft-grey-htmltrust-00.xml

Large diffs are not rendered by default.

232 changes: 232 additions & 0 deletions ietf-draft/vectors/signing-profile-v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
{
"description": "HTMLTrust signing profile v1 vector from canonical content and normalized claim records",
"profile": {
"signature": "htmltrust-signature-v1",
"canonicalization": "htmltrust-c14n-v1",
"attributes": "htmltrust-attrs-v1",
"url": "htmltrust-safe-url-v1",
"context": "https://htmltrust.org/protocol/signed-section"
},
"key": {
"seedHex": "68746d6c74727573742d746573742d766563746f722d656432353531392d3031",
"publicKeyRawHex": "ae8e474e7921dd51be650dcf6847ab452dee63421339efc3d6b041b2e85f4c19"
},
"input": {
"documentURL": "HTTPS://EXAMPLE.COM:443/essays/engines#analysis",
"attributes": {
"profile": "htmltrust-signature-v1",
"signature-scope": "url",
"keyid": "https://keys.example/alice-2026.json",
"algorithm": "ed25519",
"content-hash": "sha256:IVAwpRTDujszmYf76W497alVTtxGCgtJtQlasiFSCM8"
},
"canonicalContent": "On Analytical Engines\nThe engine weaves algebraic patterns - just as the loom weaves flowers.\nSee @attr:a:href:https://example.com/notes/engine\nthe notes and @attr:img:src:https://example.com/img/ada.png\n@attr:img:alt:Portrait of Ada\n.",
"normalizedClaims": [
{
"name": "author",
"content": "Ada Lovelace"
},
{
"name": "claim:License",
"content": "CC-BY-4.0"
},
{
"name": "signed-at",
"content": "2026-01-15T12:00:00Z"
}
],
"canonicalClaims": "author:Ada Lovelace\nclaim\\:License:CC-BY-4.0\nsigned-at:2026-01-15T12\\:00\\:00Z\n",
"signedAt": "2026-01-15T12:00:00Z"
},
"claimsHash": "sha256:Fk5udwCnu1au8v5oaBsU+aSB5S2zSLqoF0xXO6HrIn4",
"signingObject": {
"algorithm": "ed25519",
"attributeProfile": "htmltrust-attrs-v1",
"canonicalizationProfile": "htmltrust-c14n-v1",
"claimsHash": "sha256:Fk5udwCnu1au8v5oaBsU+aSB5S2zSLqoF0xXO6HrIn4",
"contentHash": "sha256:IVAwpRTDujszmYf76W497alVTtxGCgtJtQlasiFSCM8",
"context": "https://htmltrust.org/protocol/signed-section",
"keyid": "https://keys.example/alice-2026.json",
"location": "https://example.com/essays/engines",
"profile": "htmltrust-signature-v1",
"scope": "url",
"signedAt": "2026-01-15T12:00:00Z",
"urlProfile": "htmltrust-safe-url-v1"
},
"jcs": "{\"algorithm\":\"ed25519\",\"attributeProfile\":\"htmltrust-attrs-v1\",\"canonicalizationProfile\":\"htmltrust-c14n-v1\",\"claimsHash\":\"sha256:Fk5udwCnu1au8v5oaBsU+aSB5S2zSLqoF0xXO6HrIn4\",\"contentHash\":\"sha256:IVAwpRTDujszmYf76W497alVTtxGCgtJtQlasiFSCM8\",\"context\":\"https://htmltrust.org/protocol/signed-section\",\"keyid\":\"https://keys.example/alice-2026.json\",\"location\":\"https://example.com/essays/engines\",\"profile\":\"htmltrust-signature-v1\",\"scope\":\"url\",\"signedAt\":\"2026-01-15T12:00:00Z\",\"urlProfile\":\"htmltrust-safe-url-v1\"}",
"signature": "m0ykSPqUWdyZprUAqosOB2IEK2XsKp7auPIWz80/2ht+LwT1LiNcsLL6cn2IkmTZFG9ptLiUHaB1crPJgBw7BA",
"tamperFields": [
"algorithm",
"attributeProfile",
"canonicalizationProfile",
"claimsHash",
"contentHash",
"context",
"keyid",
"location",
"profile",
"scope",
"signedAt",
"urlProfile"
],
"signatureCases": [
{
"value": "m0ykSPqUWdyZprUAqosOB2IEK2XsKp7auPIWz80/2ht+LwT1LiNcsLL6cn2IkmTZFG9ptLiUHaB1crPJgBw7BA",
"valid": true
},
{
"value": "m0ykSPqUWdyZprUAqosOB2IEK2XsKp7auPIWz80/2ht+LwT1LiNcsLL6cn2IkmTZFG9ptLiUHaB1crPJgBw7BA=",
"failure": "invalid-encoding"
},
{
"value": "***",
"failure": "invalid-encoding"
},
{
"value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"failure": "malformed-signature"
},
{
"value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"failure": "signature-invalid"
}
],
"locationCases": [
{
"documentURL": "HTTPS://BÜCHER.EXAMPLE:443/a/../article?q=1#part",
"scope": "url",
"location": "https://xn--bcher-kva.example/article?q=1"
},
{
"documentURL": "https://example.org:8443/a?q=1#part",
"scope": "origin",
"location": "https://example.org:8443"
},
{
"documentURL": "https://example.org:8443/completely/different?query=2",
"scope": "origin",
"location": "https://example.org:8443"
},
{
"documentURL": "https://user@example.org/article",
"scope": "url",
"failure": "origin-not-supported"
},
{
"documentURL": "http://example.org/article",
"scope": "url",
"failure": "origin-not-supported"
},
{
"documentURL": "file:///home/example/article.html",
"scope": "origin",
"failure": "origin-not-supported"
},
{
"documentURL": "not a URL",
"scope": "url",
"failure": "origin-not-supported"
},
{
"documentURL": "https://example.org/article",
"scope": "path",
"failure": "scope-unsupported"
}
],
"timestampCases": [
{
"value": "2024-02-29T23:59:59Z",
"valid": true
},
{
"value": "2023-02-29T23:59:59Z",
"failure": "timestamp-invalid"
},
{
"value": "2026-01-15T12:00:60Z",
"failure": "timestamp-invalid"
},
{
"value": "2026-01-15T12:00:00.000Z",
"failure": "timestamp-invalid"
},
{
"value": "2026-01-15t12:00:00z",
"failure": "timestamp-invalid"
},
{
"value": "2026-01-15T07:00:00-05:00",
"failure": "timestamp-invalid"
},
{
"value": "0000-01-15T12:00:00Z",
"failure": "timestamp-invalid"
},
{
"value": "2026-13-15T12:00:00Z",
"failure": "timestamp-invalid"
}
],
"urlPolicyCases": [
{
"baseURL": "https://example.org/articles/one",
"value": "../notes?q=1#proof",
"url": "https://example.org/notes?q=1#proof"
},
{
"baseURL": "https://example.org/articles/one",
"value": "javascript:alert(1)",
"failure": "url-policy-violation"
},
{
"baseURL": "https://example.org/articles/one",
"value": "data:text/plain,hello",
"failure": "url-policy-violation"
},
{
"baseURL": "https://example.org/articles/one",
"value": "blob:https://example.org/1234",
"failure": "url-policy-violation"
},
{
"baseURL": "https://example.org/articles/one",
"value": "file:///home/example/report.pdf",
"failure": "url-policy-violation"
},
{
"baseURL": "https://example.org/articles/one",
"value": "mailto:alice@example.org",
"failure": "url-policy-violation"
},
{
"baseURL": "https://example.org/articles/one",
"value": "tel:+15551234567",
"failure": "url-policy-violation"
},
{
"baseURL": "https://example.org/articles/one",
"value": "web+example:opaque",
"failure": "url-policy-violation"
},
{
"baseURL": "https://example.org/articles/one",
"value": "http://example.org/plaintext",
"failure": "url-policy-violation"
},
{
"baseURL": "https://example.org/articles/one",
"value": "https://user:secret@example.org/private",
"failure": "url-policy-violation"
},
{
"baseURL": "https://example.org/articles/one",
"value": "https://example.org/line\nbreak",
"failure": "url-policy-violation"
},
{
"baseURL": "not a URL",
"value": "relative",
"failure": "attribute-canonicalization-failed"
}
]
}
Loading
Loading