Skip to content

Commit 1e48a48

Browse files
committed
Add RFC-006: Signatures in HTML
1 parent 23d1895 commit 1e48a48

2 files changed

Lines changed: 188 additions & 0 deletions

File tree

rfc/006-signatures-html/index.html

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>Dillo RFC-006: Signatures in HTML</title>
5+
<!-- The RFC is also signed :-) -->
6+
<link rel="signature" type="application/pgp-signature" href="index.html.sig">
7+
<style>
8+
body {
9+
background: white;
10+
line-height: 1.5;
11+
margin: 3em;
12+
font-size: 16px;
13+
font-family: sans-serif;
14+
max-width: 72ch;
15+
}
16+
h1 { font-size: 24px; margin-bottom: 1em; }
17+
header { border: solid 1px #ddd; background: #f5f5f5; padding: 0.25em 1em }
18+
dt { font-weight: bold }
19+
dd { margin-left: 2ch; }
20+
ol { margin-left: 2ch; }
21+
pre { margin: 0.5em; }
22+
</style>
23+
</head>
24+
<body>
25+
<h1>Dillo RFC-006: Signatures in HTML</h1>
26+
<header>
27+
<dl>
28+
<dt>State</dt><dd>Draft</dd>
29+
<dt>Updated</dt><dd>2025-11-15</dd>
30+
<dt>Author</dt><dd>Rodrigo Arias Mallo
31+
(<a href="mailto:rodarima@gmail.com">rodarima@gmail.com</a>)
32+
</dd>
33+
</dl>
34+
</header>
35+
<main>
36+
<h2>Abstract</h2>
37+
38+
<p>This document introduces a new link tag to specify a signature in HTML
39+
documents based on OpenPGP. It also describes how to present the signature
40+
information to users reading the document and how to verify it.</p>
41+
42+
<h2>Motivation</h2>
43+
44+
<p>When a user fetches an HTML document via the HTTPS protocol from a given
45+
site, the user can trust that the site is legitimate by checking the TLS
46+
certificate and follow the chain until a trusted CA. However, losing the DNS
47+
record of the site would cause all content to lose the trust that it had
48+
originally, even if the content is copied verbatim elsewhere.
49+
50+
<p>A mirrored copy cannot be trusted unless the author controls the
51+
mirror server as well.
52+
53+
<p>Signing the HTML document itself would allow users to verify that the
54+
content is legitimate and has not been tampered with, regardless of the
55+
transport mechanism used to deliver it to the user.
56+
57+
<p>The <a href="https://www.rfc-editor.org/rfc/rfc9580">OpenPGP specification
58+
RFC-9580</a> describes an standard on how to sign and verify
59+
signatures and several implementations are widely available to users, so it
60+
will be used as the signature format.
61+
62+
<h2>Introduction</h2>
63+
64+
<p>An OpenPGP signature is added to an HTML document by first including a
65+
<code>link</code> tag in the <code>head</code> section with the following
66+
three mandatory attributes:
67+
<ul>
68+
<li>The <code>rel</code> attribute must be set to
69+
<code>signature</code>.</li>
70+
<li>The <code>type</code> attribute must be set to the MIME type of the
71+
OpenPGP signature file which is
72+
<code>application/pgp-signature</code>.</li>
73+
<li>The <code>href</code> attribute must be set to the location of the
74+
signature file.</li>
75+
</ul>
76+
77+
<p>Multiple signatures can be added by including multiple <code>link</code>
78+
tags in the head. All signature tags must be added to the HTML document
79+
before the signatures are created. The signature files are then computed
80+
from the HTML document and placed in their respective files as described by
81+
the <code>href</code> attribute.
82+
83+
<h3>Example with GnuPG</h3>
84+
<p>To add an OpenPGP signature to an <code>index.html</code> HTML
85+
document using GnuPG:
86+
<ol>
87+
<li>Include a <code>link</code> tag in the head with the attribute
88+
<code>rel="signature"</code> as follows:
89+
<pre>&lt;link rel="signature"
90+
type="application/pgp-signature"
91+
href="index.html.sig"&gt;</pre>
92+
</li>
93+
<li>Sign the HTML document and generate a detached signature with the
94+
specified name. Example with GnuPG:
95+
<pre>$ gpg --output index.html.sig --detach-sig index.html</pre>
96+
</li>
97+
<li>Download both the HTML and signature files then verify that the
98+
signature matches. Example with GnuPG:
99+
<pre>$ gpg --verify index.html.sig index.html</pre>
100+
</li>
101+
</ol>
102+
<p>This HTML document is also signed following the above steps.</p>
103+
104+
<h2>Limitations</h2>
105+
106+
<p>The signature <strong>only covers the HTML file</strong>, not any
107+
external resource that may be referenced such as CSS, JS, images, fonts or
108+
documents in iframes. Those resources could be altered in such a way that
109+
the content of the document may change.
110+
111+
<p>A simple example can be build with a <code>style.css</code> like so:
112+
<pre>.hide { display: none; }</pre>
113+
114+
<p>And a segment of <code>index.html</code> that hides content when the CSS
115+
file is loaded, changing the meaning of the sentence:
116+
<pre>I &lt;span class=hide&gt;don't&lt;/span&gt; accept the contract.</pre>
117+
118+
<p>Similarly, CSS media rules or JavaScript code may cause elements to
119+
change causing the meaning to change depending on the user reading the
120+
document or other factors.
121+
122+
<p>Authors should not include any additional resources in a signed HTML
123+
file. They won't be loaded when a user requests to see the HTML signed
124+
document only.
125+
126+
<h2>Considerations</h2>
127+
128+
<p>The current model assumes that authors won't create misleading
129+
documents, as it would be possible to change the meaning of the document
130+
even without including external resources, using embedded JS or CSS rules.
131+
132+
<p>It is not enough to verify that a signature is valid, the key must be
133+
trusted by the user reading the document. Otherwise an actor could simply
134+
sign a changed document with its own key and pretend it is the original
135+
author. Users are expected to know how the web of trust works.
136+
137+
<p>An attacker that is able to control the content of the HTML document
138+
(for example transmitted over HTTP) could simply remove any signatures and
139+
tamper the document. We assume that trust cannot be established unless a
140+
valid signature is present.
141+
142+
<p>The type of the signature is exclusively determined by the
143+
<code>type</code> attribute in the HTML document and is therefore signed as
144+
well, so that it is not possible for an attacker to modify the Content-Type
145+
in the HTTP headers of the signature file to confuse the user agent and
146+
cause it to consider the signature not recognized.
147+
148+
<h2>Usage by user agents</h2>
149+
150+
<p>When a user agent (i.e web browser) loads a document that contains a
151+
signature it should inform the user of its presence. A user must be able to
152+
distinguish if a document has a signature compared with a document without a
153+
signature.
154+
155+
<p>The user can then request all signatures to be verified, which should
156+
indicate who signed the document and if the signature is valid.
157+
158+
<p>To verify the signature(s), the user agent downloads all signatures and
159+
runs the verification process for each. The output of the verification
160+
should be displayed to the user, indicating the level of trust on the
161+
signatures. Signatures with a non-recognized type should be indicated as
162+
such.
163+
164+
<p>User agents should detect if a document contains external resources (CSS,
165+
JS, images...) and inform the user if that is the case. The user should be
166+
able to see the rendered document without including any external resources.
167+
168+
<h2>Provisions</h2>
169+
170+
<p>The current signature tag can be extended to include other types apart
171+
from OpenPGP. The type attribute should be changed to the corresponding MIME
172+
type of the format used.
173+
174+
<p>It is expected that other types of signatures also provide a mechanism to
175+
determine the authenticity of the signature owner.
176+
177+
<h2>See also</h2>
178+
<ul>
179+
<li>James Tomasino,
180+
<i><a href="https://labs.tomasino.org/signing-posts-with-gpg/">
181+
Signing Posts with gpg</a></i> (2023)</li>
182+
<li>Pouya Abbassi,
183+
<i><a href="https://pouyacode.net/signing-webpages.html">
184+
Signing HTML documents using PGP</a></i> (2021)</li>
185+
</ul>
186+
</main>
187+
</body>
188+
</html>
310 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)