Subject: Re: [openpgp] I-D Action: draft-ietf-openpgp-crypto-refresh-02.txt (fwd)

From: Paul Wouters <[email-masked]>
Date: Mon, 22 Feb 2021 21:19:03 -0500 (EST)

Hi,

I pushed an updated version of the crypto refresh document:

https://www.ietf.org/rfcdiff?url2=draft-ietf-openpgp-crypto-refresh-02

I've also pushed the git changes to https://gitlab.com/openpgp-wg/rfc4880bis

The commit on white space changes was reverted, as the WG will be
re-opening that discussion later once we have all the consensus
items from the previous 4880bis discussion re-published in this
document.

The following items were merged in:

- Produce 4-level-deep ToC
- Reserve codepoints in the registries
- reorganize signature and asymmetric key value fields
- Re-flow the v3 and v4 signature descriptions
- Incorporated RFC 6637 (ECDSA and ECDH, using NIST curves)
- textual cleanup (no substantive changes)
- Update most registries to be SPECIFICATION REQUIRED
- Deprecate v3 signatures
- Deprecate non-integrity-protected encryption
- Include SHA3
- Incorporate Curve25519 for ECDH
- Add ECC Point compression flag bytes appendix section
- update reference RFC2434 to RFC8126

Please review the changes and let the WG know of any issues you see.
This includes if you think something was merged that did not have WG
consensus.

Paul

---

From: "Derek Atkins" <[email-masked]>
Date: Tue, 23 Feb 2021 08:15:06 -0500

Hi,

Current text says:

   Implementations SHOULD generate V4 signatures.  Implementations MUST
   NOT create version 3 signatures; they MAY accept version 3
   signatures.

There is no MUST create version.  Is this intended to change?

Later (5.8):

   This packet is obsolete.  An implementation MUST NOT create this
   packet.  An implementation MAY process such a packet but it MUST
   return a clear diagnostic that a non-integrity protected packet has
   been processed.  The implementation SHOULD also return an error in
   this case and stop processing.

I'm confused by this text.  If an implementation chooses to process this
packet type (e.g. I have 20-year-old PGP-encrypted messages that I'd still
like to be able to read without re-encrypting them), why are you saying
that it should return an error and stop processing?  So it MAY process but
SHOULD stop processing?  I'm confused.

Those were the only issues I noticed reading through this version.

Thank you for your hard work!

-derek

On Mon, February 22, 2021 9:19 pm, Paul Wouters wrote:
> _______________________________________________
> openpgp mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/openpgp
>

-- 
       Derek Atkins                 617-623-3745
       [email-masked]             www.ihtfp.com
       Computer and Internet Security Consultant

---

From: "Robert J. Hansen" <[email-masked]>
Date: Tue, 23 Feb 2021 11:10:35 -0500

> I'm confused by this text.  If an implementation chooses to process 
> this packet type (e.g. I have 20-year-old PGP-encrypted messages
> that I'd still like to be able to read without re-encrypting them),
> why are you saying that it should return an error and stop
> processing? So it MAY process but SHOULD stop processing?  I'm
> confused.

"MAY process but SHOULD stop" is the way I'd read that guidance:
although a conforming implementation technically may process the packet,
it should not do so absent a compelling reason.

Perhaps this text instead?

"This packet is obsolete.  An implementation MUST NOT create this
packet.  An implementation MAY process such a packet but it MUST
return a clear diagnostic that a non-integrity protected packet has
been processed.  Unless the user explicitly directs otherwise, the
implementation SHOULD also return an error in this case and stop
processing."

---

From: Werner Koch <[email-masked]>
Date: Tue, 23 Feb 2021 18:16:06 +0100

> There is no MUST create version.  Is this intended to change?

This is is an editorial problem due to our step by step re-iteration
process.  The dropped draft-ietf-openpgp-rfc4880bis-10.txt had this text:

   Implementations MUST generate version 5 signatures when using a
   version 5 key.  Implementations SHOULD generate V4 signatures with
   version 4 keys.  Implementations MUST NOT create version 3
   signatures; they MAY accept version 3 signatures.

which should explain above.  But right in the course of re-iteration
Paul and me should have noticed that and adjusted it accordingly.

Shalom-Salam,

   Werner

-- 
Die Gedanken sind frei.  Ausnahmen regelt ein Bundesgesetz.

---

From: "Derek Atkins" <[email-masked]>
Date: Tue, 23 Feb 2021 12:24:32 -0500

HI,

> Paul and me should have noticed that and adjusted it accordingly.

Okay, so this is "intended to change" are more edits are done.
Gotcha.

-derek

---

From: Ángel <[email-masked]>
Date: Fri, 26 Feb 2021 02:19:47 +0100

Hello all

After reviewing these two drafts, I agree there are no substantial
changes in draft-ietf-openpgp-crypto-refresh-00.txt from rfc4880, and
consider draft-ietf-openpgp-crypto-refresh-02.txt good to iterate from.

Some specific comments are provided below.

Looking forward to seeing you all at the meeting.

- Ángel

crypto-refresh-00 nitpicks
=====

I would prefer to keep single quotes for values referring to single
bytes standing by themselves, as rfc4880 did. -00 changed them to
double quotes but using single quotes as in C seems better.

This happens in
* 5.9.  Literal Data Packet (Tag 11)
('b', 't', 'u', 'l', '1') vs ("b", "t", "u", "l", "1")

* 6.2.  Forming ASCII Armor with '-' and ':'
* 7.1.  Dash-Escaped Text with '-'

but does *not* apply to the characters in 8. Regular Expressions

Additionally, in 7.1 a single-quoted space (' ') was
converted to use backticks (` `), which seems like an
error when converting the document. It makes sense
in some markdown conversions, but not in the rfc results.

In appendix A, an extra space was inserted between "Philip R." 
and "Zimmermann" (Appendix C in -02)

crypto-refresh-01/02 nitpicks
=====
At 1. Introduction, change "RFC 5581 (Camellia cipher)" to "RFC 5581
(The Camellia Cipher in OpenPGP)" or "RFC 5581 (Camellia Cipher in
OpenPGP)", since just "Camellia cipher" could be confused with the
description itself of Camellia (rfc3713).
"ECC for OpenPGP" should perhaps be changed to "ECC in OpenPGP" which is the
preposition used in that rfc title.
Full name of RFC 6637 is "Elliptic Curve Cryptography (ECC) in OpenPGP" and
would be the proper one if we wanted to use the complete names of the rfc,
albeit I don't think that would matter either way.

I would prefer to see the new section "ECC Curve OID" as 9.5 instead of 9.2

---

From: Ángel <[email-masked]>
Date: Fri, 26 Feb 2021 02:25:49 +0100

Hello all

- Ángel

This happens in

I would prefer to see the new section "ECC Curve OID" as 9.5 instead of 9.2
The other blocks are clear registries used directly. "ECC Curve OID"
are a different case since they are actually parameter inside Public key with
certain ids. It's probably as 9.2 because a former draft likely referred to it
from 9.1, but that doesn't seem to be the case, and is only referred from other
completely separate sections.

I'm not too keen on the way this section is introduced. I may provide a MR if
I can come up with something.

10.2.2.2.  Signature Notation Data Subpacket Notation Flags creates a new registry
but it doesn't point to a section with initial values. 
It should probably link to table 7 of section 5.2.3.16, although that would need
additional columns.

Procedural question: is it the right thing for a RFC to state that it "creates a
new registry" for those registries which were actually created by an older RFC
it is obsoleting?

I feel the text added at 15.  Security Considerations still needs some revision. 
Maybe split part of it to a different section. There are too many things there,
and it seems hard to grasp everything it mixes.

As a concrete suggestion, I would recommend adding Compatibility
Profiles as section 15 instead of 16. Security Considerations (SC)
refers to Compatibility Profiles (CP) and Compatibility
Profiles refers to Security Considerations, but it seems it would be
easier to read Compatibility Profiles first (assuming a linear reading
of the rfc). Reference to (SC) is easier to skip (there will be some
algorithm choices at that section), whereas the reference
to CP is murkier: 
> Requirement levels indicated elsewhere in this document lead to	
> the following combinations of algorithms in the OpenPGP profile:
> MUST implement P-256 / SHA2-256 / AES-128 / SHOULD implement ...

when the reader hasn't been told about OpenPGP profiles and, in fact,
some of those algorithms it shows as a MUST are optional at 9.1 / 9.3

An introduction should be added after "16. Compatibility Profiles"
and before "16.1" explaining what are Compatibility Profiles and why
would they be interesting / needed.

You may want to put the temporary Document Workflow appendix as C,
so that the other two won't need renumbering on publication.

---

From: "Neal H. Walfield" <[email-masked]>
Date: Fri, 26 Feb 2021 12:46:45 +0100

On Tue, 23 Feb 2021 03:19:03 +0100,
> - Incorporated RFC 6637 (ECDSA and ECDH, using NIST curves)

In the OpenPGP ECC Profile section, SHA2-384 is listed as a SHOULD
algorithm:

  ## OpenPGP ECC Profile

  A compliant application MUST implement SHA2-256 and SHOULD implement
  SHA2-384 and SHA2-512.

But, in the 'Hash Algorithms' section, it is a MAY algorithm.

  ## Hash Algorithms

  Implementations MUST implement SHA-1.
  Implementations MAY implement other algorithms.
  MD5 is deprecated.

In the 'Security Considerations' section there are two relevant
points:

  # Security Considerations

  - Requirement levels indicated elsewhere in this document lead to
    the following combinations of algorithms in the OpenPGP profile:
    MUST implement NIST curve P-256 / SHA2-256 / AES-128, SHOULD
    implement NIST curve P-521 / SHA2-512 / AES-256, MAY implement
    NIST curve P-384 / SHA2-384 / AES-256, among other allowed
    combinations.

  - SHA2-224 and SHA2-384 require the same work as SHA2-256 and
    SHA2-512, respectively.  In general, there are few reasons to use
    them outside of DSS compatibility.

So, ECC that uses SHA2-384 is a MAY and SHA2-384 is discouraged.

In the past, we've talked about algorithm agility on this mailing
list:

  http://mailarchive.ietf.org/arch/msg/openpgp/2C5jQNKcnUZZUzh84s0Di-GYKV0

And the last version of 4880bis only included SHA3-256 and SHA3-512.

  https://gitlab.com/openpgp-wg/rfc4880bis/-/blob/main/draft-ietf-openpgp-rfc4880bis-09.txt#L3801

My suggestion is to change the following text:

  A compliant application MUST implement SHA2-256 and SHOULD implement
  SHA2-384 and SHA2-512.

to

  A compliant application MUST implement SHA2-256 and SHOULD implement
  SHA2-512.  It MAY implement SHA2-384.

Neal

---

From: "Neal H. Walfield" <[email-masked]>
Date: Fri, 26 Feb 2021 12:50:17 +0100

> - Incorporated RFC 6637 (ECDSA and ECDH, using NIST curves)

While reading this change, I encountered some unfortunate wordings and
inconsistent formatting.  This patch, which is hopefully
uncontroversial, fixes those issues.

:) Neal

From 54faf5c3f184b3470ccda5938688f482a68838fc Mon Sep 17 00:00:00 2001
From: "Neal H. Walfield" <[email-masked]>
Date: Thu, 25 Feb 2021 14:17:22 +0100
Subject: [PATCH] Copy edit 3f09f3c56e14be92007c12622eac889d7f58a8e0 (ECC).

  - Correct use of comma.

  - Use capital hex.

  - Mimic list structure in the rest of the document.

  - Improve a few awkward sentences.
---
 crypto-refresh.md | 108 +++++++++++++++++++++++-----------------------
 1 file changed, 54 insertions(+), 54 deletions(-)

diff --git a/crypto-refresh.md b/crypto-refresh.md
index 32e7927..2a9e166 100644
--- a/crypto-refresh.md
+++ b/crypto-refresh.md
@@ -757,7 +757,7 @@ The body of this packet consists of:
 
   - MPI of an EC point representing an ephemeral public key.
 
-  - a one-octet size, followed by a symmetric key encoded using the method described in {{ec-dh-algorithm-ecdh}}.
+  - A one-octet size, followed by a symmetric key encoded using the method described in {{ec-dh-algorithm-ecdh}}.
 
 The value "m" in the above formulas is derived from the session key as follows.
 First, the session key is prefixed with a one-octet algorithm identifier that specifies the symmetric encryption algorithm used to encrypt the following Symmetrically Encrypted Data Packet.
@@ -1760,13 +1760,13 @@ The secret key is this single multiprecision integer:
 
 The public key is this series of values:
 
-- a variable-length field containing a curve OID, formatted as follows:
+- A variable-length field containing a curve OID, which is formatted as follows:
 
-  - a one-octet size of the following field; values 0 and 0xFF are reserved for future extensions,
+  - A one-octet size of the following field; values 0 and 0xFF are reserved for future extensions,
 
-  - the octets representing a curve OID, defined in {{ecc-curve-oid}};
+  - The octets representing a curve OID (defined in {{ecc-curve-oid}});
 
-- a MPI of an EC point representing a public key.
+- MPI of an EC point representing a public key.
 
 The secret key is this single multiprecision integer:
 
@@ -1776,25 +1776,25 @@ The secret key is this single multiprecision integer:
 
 The public key is this series of values:
 
-- a variable-length field containing a curve OID, formatted as follows:
+- A variable-length field containing a curve OID, which is formatted as follows:
 
-  - a one-octet size of the following field; values 0 and 0xFF are reserved for future extensions,
+  - A one-octet size of the following field; values 0 and 0xFF are reserved for future extensions,
 
-  - the octets representing a curve OID, defined in {{ecc-curve-oid}};
+  - Octets representing a curve OID, defined in {{ecc-curve-oid}};
 
-- a MPI of an EC point representing a public key;
+- MPI of an EC point representing a public key;
 
-- a variable-length field containing KDF parameters, formatted as follows:
+- A variable-length field containing KDF parameters, which is formatted as follows:
 
-  - a one-octet size of the following fields; values 0 and 0xff are reserved for future extensions;
+  - A one-octet size of the following fields; values 0 and 0xFF are reserved for future extensions,
 
-  - a one-octet value 1, reserved for future extensions;
+  - A one-octet value 1, reserved for future extensions,
 
-  - a one-octet hash function ID used with a KDF;
+  - A one-octet hash function ID used with a KDF,
 
-  - a one-octet algorithm ID for the symmetric algorithm used to wrap the symmetric key used for the message encryption; see {{ec-dh-algorithm-ecdh}} for details.
+  - A one-octet algorithm ID for the symmetric algorithm used to wrap the symmetric key used for the message encryption; see {{ec-dh-algorithm-ecdh}} for details.
 
-Observe that an ECDH public key is composed of the same sequence of fields that define an ECDSA key, plus the KDF parameters field.
+Observe that an ECDH public key is composed of the same sequence of fields that define an ECDSA key plus the KDF parameters field.
 
 The secret key is this single multiprecision integer:
 
@@ -2433,7 +2433,7 @@ See {{reserved-notes}} for notes on Elgamal Encrypt or Sign (20), and X9.42 (21)
 Implementations MAY implement any other algorithm.

-A compatible specification of ECDSA is given in {{RFC6090}} as "KT-I Signatures" and in {{SEC1}}; ECDH is defined in {{ec-dh-algorithm-ecdh}} this document.
+A compatible specification of ECDSA is given in {{RFC6090}} as "KT-I Signatures" and in {{SEC1}}; ECDH is defined in {{ec-dh-algorithm-ecdh}} of this document.
 
 ## ECC Curve OID
 
@@ -2867,7 +2867,7 @@ A thorough introduction to ECC can be found in {{KOBLITZ}}.
 
 ## Supported ECC Curves
 
-This document references three named prime field curves, defined in {{FIPS186}} as "Curve P-256", "Curve P-384", and "Curve P-521".
+This document references three named prime field curves defined in {{FIPS186}} as "Curve P-256", "Curve P-384", and "Curve P-521".
 Further curve "Curve25519", defined in {{RFC7748}} is referenced for use with X25519 (ECDH encryption).
 
 The named curves are referenced as a sequence of bytes in this document, called throughout, curve OID.
@@ -2882,15 +2882,15 @@ For an uncompressed point the content of the MPI is:
 
     B = 04 || x || y
 
-where x and y are coordinates of the point P = (x, y), each encoded in the big-endian format and zero-padded to the adjusted underlying field size.
-The adjusted underlying field size is the underlying field size that is rounded up to the nearest 8-bit boundary.
+where x and y are coordinates of the point P = (x, y), and each is encoded in the big-endian format and zero-padded to the adjusted underlying field size.
+The adjusted underlying field size is the underlying field size rounded up to the nearest 8-bit boundary.
 This encoding is compatible with the definition given in {{SEC1}}.
 
 For a custom compressed point the content of the MPI is:
 
     B = 40 || x
 
-where x is the x coordinate of the point P encoded to the rules defined for the specified curve.
+where x is the x coordinate of the point P encoded using the rules defined for the specified curve.
 This format is used for ECDH keys based on curves expressed in Montgomery form.
 
 Therefore, the exact size of the MPI payload is 515 bits for "Curve P-256", 771 for "Curve P-384", 1059 for "Curve P-521", and 263 for Curve25519.
@@ -2902,7 +2902,7 @@ Consider, for example, that while both the public key and the per-recipient ECDH
 
 ## Key Derivation Function
 
-A key derivation function (KDF) is necessary to implement the EC encryption.
+A key derivation function (KDF) is necessary to implement EC encryption.
 The Concatenation Key Derivation Function (Approved Alternative 1) {{SP800-56A}} with the KDF hash function that is SHA2-256 {{FIPS180}} or stronger is REQUIRED.
 See {{compatibility-profiles}} for the details regarding the choice of the hash function.
 
@@ -2922,65 +2922,65 @@ However, {{SP800-56A}} is the normative source of the definition.
     MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param );
     return oBits leftmost bits of MB.
 
-Note that ZB in the KDF description above is the compact representation of X, defined in Section 4.2 of {{RFC6090}}.
+Note that ZB in the KDF description above is the compact representation of X as defined in Section 4.2 of {{RFC6090}}.
 
 ## EC DH Algorithm (ECDH)
 
 The method is a combination of an ECC Diffie-Hellman method to establish a shared secret, a key derivation method to process the shared secret into a derived key, and a key wrapping method that uses the derived key to protect a session key used to encrypt a message.
 
-The One-Pass Diffie-Hellman method C(1, 1, ECC CDH) {{SP800-56A}} MUST be implemented with the following restrictions: the ECC CDH primitive employed by this method is modified to always assume the cofactor as 1, the KDF specified in {{key-derivation-function}} is used, and the KDF parameters specified below are used.
+The One-Pass Diffie-Hellman method C(1, 1, ECC CDH) {{SP800-56A}} MUST be implemented with the following restrictions: the ECC CDH primitive employed by this method is modified to always assume the cofactor is 1, the KDF specified in {{key-derivation-function}} is used, and the KDF parameters specified below are used.
 
-The KDF parameters are encoded as a concatenation of the following 5 variable-length and fixed-length fields, compatible with the definition of the OtherInfo bitstring {{SP800-56A}}:
+The KDF parameters are encoded as a concatenation of the following 5 variable-length and fixed-length fields, which are compatible with the definition of the OtherInfo bitstring {{SP800-56A}}:
 
-- a variable-length field containing a curve OID, formatted as follows:
+- A variable-length field containing a curve OID, which is formatted as follows:
 
-  - a one-octet size of the following field
+  - A one-octet size of the following field,
 
-  - the octets representing a curve OID, defined in {{ecc-curve-oid}}
+  - The octets representing a curve OID defined in {{ecc-curve-oid}};
 
-- a one-octet public key algorithm ID defined in {{pubkey-algos}}
+- A one-octet public key algorithm ID defined in {{pubkey-algos}};
 
-- a variable-length field containing KDF parameters, identical to the corresponding field in the ECDH public key, formatted as follows:
+- A variable-length field containing KDF parameters, which are identical to the corresponding field in the ECDH public key, and are formatted as follows:
 
-  - a one-octet size of the following fields; values 0 and 0xff are reserved for future extensions
+  - A one-octet size of the following fields; values 0 and 0xFF are reserved for future extensions,
 
-  - a one-octet value 01, reserved for future extensions
+  - A one-octet value 0x01, reserved for future extensions,
 
-  - a one-octet hash function ID used with the KDF
+  - A one-octet hash function ID used with the KDF,
 
-  - a one-octet algorithm ID for the symmetric algorithm used to wrap the symmetric key for message encryption; see {{ec-dh-algorithm-ecdh}} for details
+  - A one-octet algorithm ID for the symmetric algorithm used to wrap the symmetric key for message encryption; see {{ec-dh-algorithm-ecdh}} for details;
 
-- 20 octets representing the UTF-8 encoding of the string `Anonymous Sender    `, which is the octet sequence 41 6E 6F 6E 79 6D 6F 75 73 20 53 65 6E 64 65 72 20 20 20 20
+- 20 octets representing the UTF-8 encoding of the string `Anonymous Sender    `, which is the octet sequence 41 6E 6F 6E 79 6D 6F 75 73 20 53 65 6E 64 65 72 20 20 20 20;
 
-- 20 octets representing a recipient encryption subkey or a master key fingerprint, identifying the key material that is needed for the decryption.
-  For version 5 keys the 20 leftmost octets of the fingerprint are used.
+- [ ] 20 octets representing a recipient encryption subkey or a primary key fingerprint identifying the key material that is needed for decryption
+  (for version 5 keys the 20 leftmost octets of the fingerprint are used).
 
 The size of the KDF parameters sequence, defined above, is either 54 for the NIST curve P-256, 51 for the curves P-384 and P-521, or 56 for Curve25519.
 
 The key wrapping method is described in {{RFC3394}}.
-KDF produces a symmetric key that is used as a key-encryption key (KEK) as specified in {{RFC3394}}.
+The KDF produces a symmetric key that is used as a key-encryption key (KEK) as specified in {{RFC3394}}.
 Refer to {{security-considerations}} for the details regarding the choice of the KEK algorithm, which SHOULD be one of three AES algorithms.
 Key wrapping and unwrapping is performed with the default initial value of {{RFC3394}}.
 
 The input to the key wrapping method is the value "m" derived from the session key, as described in {{public-key-encrypted-session-key-packets-tag-1}}, "Public-Key Encrypted Session Key Packets (Tag 1)", except that the PKCS #1.5 padding step is omitted.
-The result is padded using the method described in {{PKCS5}} to the 8-byte granularity.
+The result is padded using the method described in {{PKCS5}} to an 8-byte granularity.
 For example, the following AES-256 session key, in which 32 octets are denoted from k0 to k31, is composed to form the following 40 octet sequence:
 
-    09 k0 k1 ... k31 c0 c1 05 05 05 05 05
+    09 k0 k1 ... k31 C0 C1 05 05 05 05 05
 
-The octets c0 and c1 above denote the checksum.
+The octets C0 and C1 above denote the checksum.
 This encoding allows the sender to obfuscate the size of the symmetric encryption key used to encrypt the data.
 For example, assuming that an AES algorithm is used for the session key, the sender MAY use 21, 13, and 5 bytes of padding for AES-128, AES-192, and AES-256, respectively, to provide the same number of octets, 40 total, as an input to the key wrapping method.
 
 The output of the method consists of two fields.
 The first field is the MPI containing the ephemeral key used to establish the shared secret.
-The second field is composed of the following two fields:
+The second field is composed of the following two subfields:
 
-- a one-octet encoding the size in octets of the result of the key wrapping method; the value 255 is reserved for future extensions;
+- One octet encoding the size in octets of the result of the key wrapping method; the value 255 is reserved for future extensions;
 
-- up to 254 octets representing the result of the key wrapping method, applied to the 8-byte padded session key, as described above.
+- Up to 254 octets representing the result of the key wrapping method, applied to the 8-byte padded session key, as described above.
 
-Note that for session key sizes 128, 192, and 256 bits, the size of the result of the key wrapping method is, respectively, 32, 40, and 48 octets, unless the size obfuscation is used.
+Note that for session key sizes 128, 192, and 256 bits, the size of the result of the key wrapping method is, respectively, 32, 40, and 48 octets, unless size obfuscation is used.
 
 For convenience, the synopsis of the encoding method is given below; however, this section, {{SP800-56A}}, and {{RFC3394}} are the normative sources of the definition.
 
@@ -3011,7 +3011,7 @@ Note that the recipient obtains the shared secret by calculating
 
     S = rV = rvG, where (r,R) is the recipient's key pair.
 
-Consistent with {{seipd}}, Modification Detection Code (MDC) MUST be used anytime the symmetric key is protected by ECDH.
+Consistent with {{seipd}}, a Modification Detection Code (MDC) MUST be used anytime the symmetric key is protected by ECDH.
 
 # Notes on Algorithms {#notes-on-algorithms}
 
@@ -3448,16 +3448,16 @@ NIST P-521 | SHA2-512 | AES-256
 
   Note that the symmetric algorithm preference list may make it impossible to use the balanced strength of symmetric key algorithms for a corresponding public key.
   For example, the presence of the symmetric key algorithm IDs and their order in the key preference list affects the algorithm choices available to the encoding side, which in turn may make the adherence to the table above infeasible.
-  Therefore, compliance with this specification is a concern throughout the life of the key, starting immediately after the key generation when the key preferences are first added to a key.
+  Therefore, compliance with this specification is a concern throughout the life of the key starting immediately after the key generation when the key preferences are first added to a key.
   It is generally advisable to position a symmetric algorithm ID of strength matching the public key at the head of the key preference list.
 
   Encryption to multiple recipients often results in an unordered intersection subset.
   For example, if the first recipient's set is {A, B} and the second's is {B, A}, the intersection is an unordered set of two algorithms, A and B.
   In this case, a compliant application SHOULD choose the stronger encryption algorithm.
 
-  Resource constraints, such as limited computational power, is a likely reason why an application might prefer to use the weakest algorithm.
+  Resource constraints, such as limited computational power, are a reason why an application might prefer to use the weakest algorithm.
   On the other side of the spectrum are applications that can implement every algorithm defined in this document.
-  Most applications are expected to fall into either of two categories.
+  Most applications are expected to fall into either of these two categories.
   A compliant application in the second, or strongest, category SHOULD prefer AES-256 to AES-192.
 
   SHA-1 MUST NOT be used with the ECDSA or the KDF in the ECDH method.
@@ -3466,7 +3466,7 @@ NIST P-521 | SHA2-512 | AES-256
   None of the ECC methods described in this document are allowed with deprecated V3 keys.
   A compliant application MUST only use iterated and salted S2K to protect private keys, as defined in {{iterated-and-salted-s2k}}, "Iterated and Salted S2K".
 
-  Side channel attacks are a concern when a compliant application's use of the OpenPGP format can be modeled by a decryption or signing oracle model, for example, when an application is a network service performing decryption to unauthenticated remote users.
+  Side channel attacks are a concern when a compliant application's use of the OpenPGP format can be modeled by a decryption or signing oracle, for example, when an application is a network service performing decryption to unauthenticated remote users.
   ECC scalar multiplication operations used in ECDSA and ECDH are vulnerable to side channel attacks.
   Countermeasures can often be taken at the higher protocol level, such as limiting the number of allowed failures or time-blinding of the operations associated with each network interface.
   Mitigations at the scalar multiplication level seek to eliminate any measurable distinction between the ECC point addition and doubling operations.
@@ -3481,13 +3481,13 @@ A compliant application MUST implement AES-128 and SHOULD implement AES-256.
 
 A compliant application SHOULD follow {{security-considerations}} regarding the choice of the following algorithms for each curve:
 
-- the KDF hash algorithm,
+- The KDF hash algorithm,
 
-- the KEK algorithm,
+- The KEK algorithm,
 
-- the message digest algorithm and the hash algorithm used in the key certifications,
+- The message digest algorithm and the hash algorithm used in the key certifications,
 
-- the symmetric algorithm used for message encryption.
+- The symmetric algorithm used for message encryption.
 
 It is recommended that the chosen symmetric algorithm for message encryption be no less secure than the KEK algorithm.
 
@@ -3495,7 +3495,7 @@ It is recommended that the chosen symmetric algorithm for message encryption be
 
 A subset of algorithms allowed by this document can be used to achieve {{SuiteB}} compatibility.
 The references to {{SuiteB}} in this document are informative.
-This document is primarily concerned with format specification, leaving additional security restrictions unspecified, such as matching the assigned security level of information to authorized recipients or interoperability concerns arising from fewer allowed algorithms in {{SuiteB}} than allowed by this document.
+This document is primarily concerned with format specification and leaves additional security restrictions unspecified, such as matching the assigned security level of information to authorized recipients or interoperability concerns arising from fewer allowed algorithms in {{SuiteB}} than allowed by this document.
 
 ### Security Strength at 192 Bits
 
-- 
2.20.1

---

From: "Neal H. Walfield" <[email-masked]>
Date: Fri, 26 Feb 2021 12:53:11 +0100

Hi,

  A compliant application MUST only use iterated and salted S2K to
  protect private keys, as defined in {{iterated-and-salted-s2k}},
  "Iterated and Salted S2K".

This precludes the use of private S2K algorithms (algos 100 to 110).

  https://tools.ietf.org/html/rfc4880#section-3.7

Would a MUST NOT use Simple S2K and MUST NOT use Salted S2K be better?

:) Neal

---

From: "Neal H. Walfield" <[email-masked]>
Date: Fri, 26 Feb 2021 13:01:01 +0100

-a.2) high-order length octet of (b)-(e) (1 octet)
  -
  -a.3) low-order length octet of (b)-(e) (1 octet)
  +a.2) two-octet scalar octet count of (b)-(e)

It is less clear that the count is big endian.  Perhaps:

  a.2) two-octet, big endian scalar octet count of (b)-(e)

---

From: "Neal H. Walfield" <[email-masked]>
Date: Fri, 26 Feb 2021 13:08:53 +0100

> - Deprecate non-integrity-protected encryption

  +This packet is obsolete.
  +An implementation MUST NOT create this packet.
  +An implementation MAY process such a packet but it MUST return a clear diagnostic that a non-integrity protected packet has been processed.
  +The implementation SHOULD also return an error in this case and stop processing.

It's not clear to me how a library should warn the user.  In Sequoia,
an application has to opt-in to deprecated algorithms.  Is that
enough?

I'm also confused about the interplay between the last two sentences:
in the second-to-last sentence, an implementation "MAY process such a
packet" and in the last it "SHOULD *also* ... stop processing" (stars
mine).  Aren't these in conflict?

:) Neal

---

From: "Neal H. Walfield" <[email-masked]>
Date: Fri, 26 Feb 2021 13:14:28 +0100

> This includes if you think something was merged that did not have WG

I've reviewed the changes between -01 and -02 with exception of the
ECC changes, which I'm not qualified to evaluate.  Other than the
minor points I raised, I don't have any objections.

Thanks everyone.

:) Neal

---

From: "Neal H. Walfield" <[email-masked]>
Date: Fri, 26 Feb 2021 13:22:14 +0100

Derek raised this issue here:

   https://mailarchive.ietf.org/arch/msg/openpgp/6KrTJw1U-u9N8MJ5LIcCbSc-PVY

I apologize for the duplicate.

:) Neal

On Fri, 26 Feb 2021 13:08:53 +0100,

---

From: Daniel Kahn Gillmor <[email-masked]>
Date: Fri, 26 Feb 2021 20:42:27 -0500

>    NOT create version 3 signatures; they MAY accept version 3

As Paul and Werner both noted, this is a hiccup in the transitional
nature of the document.

I've flagged it as https://gitlab.com/openpgp-wg/rfc4880bis/-/issues/15
so that we don't lose track of it.

> There is no MUST create version.  Is this intended to change?

fwiw, (no hats on) i'm not sure that "MUST create" is the right wording
ultimately.  We want "MUST be able to create" or "MUST create [in some
specific context]" but i can't see requiring creation of a signature
type without one of those caveats.

> SHOULD stop processing?  I'm confused.

I've recorded this as
https://gitlab.com/openpgp-wg/rfc4880bis/-/issues/16 and mentioned
Robert's suggestion of how it could be re-phrased.

         --dkg

---

From: Daniel Kahn Gillmor <[email-masked]>
Date: Fri, 26 Feb 2021 23:41:04 -0500

Hi Neal--

Thanks for the nit-picks.  Two concerns:

> +  (for version 5 keys the 20 leftmost octets of the fingerprint are used).

what does the [ ] you've inserted here mean?  It looks like a markdown
todo-list "checkbox", maybe it was inserted by mistake?

> +The octets C0 and C1 above denote the checksum.

This seems like a mistake.  C0 and C1 could be specific hexadecimal
octets (decimal 12), whereas "c0" and "c1" here are intended to be
placeholders for the checksum.  This is a bit confusing, maybe it would
be better to use s0 and s1 (s for "sum") so that it's clear that it
isn't hex?

At any rate, i think this was the only "capital hex" part of the diff,
so we probably don't need that mention in the commit message either,
right?

I've included this proposal (without the two changes above that i think
are mistaken) and your other remark about the big-endianness of the
two-octet scalar in a merge request:

   https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/38

I encourage people to make merge requests directly in gitlab in addition
to posting patches to the mailing list, especially for
non-substantive/editorial changes like this.

        --dkg

---

From: Daniel Kahn Gillmor <[email-masked]>
Date: Fri, 26 Feb 2021 23:00:49 -0500

Thanks for this close read, Ángel.

You raised so many points in one message that i'm afraid some of them
might get lost.

I'm trying to address all of your concerns, either with a merge request
(MR) with a simple editorial patch, a call for further discussion, or a
new issue in gitlab.

If you want to follow up on one or the other, i recommend referring to
the specific issue or merge request in the subject of the mailing list
thread, if one exists.

I encourage folks to do this kind of tracking/triage on the issues they
raise on-list directly, it's quite a bit of work to make sure that all
the points get tracked so they can be handled.

> but does *not* apply to the characters in 8. Regular Expressions

I'm not sure how to address this request without doing some heavy
lifting in the toolchain, espcially since it looks like you want the
tooling to behave differently for characters in the two different
places.

Please take a look at the HTML rendering
(https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-02.html)
which sets off these literal string representations in a clearly
different style.  I think that's an improvement worth keeping.

I'm also not sure how much single vs double quotes matters here.  If you
want to propose a fix we can discuss it though :)

> in some markdown conversions, but not in the rfc results.

hm, yes, this looks like a bug in kramdown-rfc2629 which i've reported
here:

  https://github.com/cabo/kramdown-rfc2629/issues/108

I've proposed a formatting workaround:

   https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/34

-Dash-escaped cleartext is the ordinary cleartext where every line starting with a dash `-` (0x2D) is prefixed by the sequence dash `-` (0x2D) and space ` ` (0x20).
+Dash-escaped cleartext is the ordinary cleartext where every line starting with a <u>-</u> is prefixed by the sequence <u>-</u> and <u> </u>.

This results in  the following change in the .txt version:

[…]
    Dash-escaped cleartext is the ordinary cleartext where every line
-   starting with a dash "-" (0x2D) is prefixed by the sequence dash "-"
-   (0x2D) and space ` ` (0x20).  
+   starting with a "-" (HYPHEN-MINUS, U+002D) is prefixed by the
+   sequence "-" (HYPHEN-MINUS, U+002D) and " " (SPACE, U+0020).
[…]

Hopefully that is no less clear than before, and the rendering is more
normalized without the backticks.

> and "Zimmermann" (Appendix C in -02)

I initially thought this was an artifact of the ./reflow script.  I've
added a special case to avoid it while still being able to use ./reflow,
and suggested the fix here:

   https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/35

However, it looks like this is actually a bug in xml2rfc, which wants to
put two spaces between a period and the next sentence.

I've reported this here:

   https://mailarchive.ietf.org/arch/msg/xml2rfc/6V7C7l-zxg97jRqvuaq8r1QBQqw/

> albeit I don't think that would matter either way.

These aren't the full RFC names (4880 itself is not "OpenPGP"), they're
shorthand labels, but i agree that they should be normalized to be more
readable.  I submitted the editorial suggestion
https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/36 to make
them "Camellia in OpenPGP" and "Elliptic Curves in OpenPGP".

> completely separate sections.

There is a sense that an ECC Curve OID is a subtype of public-key
algorithms, so putting it closer to public-key algorithms is appealing.
But i think this argues not for leaving it as 9.2, but rather as a
subsection of the "Public-key Algorithms" section of the top-level
"Constants" header (i.e. 9.1.1).

fwiw, while we're nit-picking, this section ought to be named "ECC Curve
OIDs" (in the plural)

Seems like there are three choices:

 a) leave "ECC Curve OIDs" as §9.2

 b) make "ECC Curve OIDs" a subsection of "§9.1 Public-key Algorithms",
    i.e., §9.1.1

 c) move "ECC Curve OIDs" to the end of the "§9 Constants", i.e., §9.5

What do other folks think?

> I can come up with something.

Please do propose an MR.

> It should probably link to table 7 of section 5.2.3.16, although that would need

Good catch!  I'm not even sure what the "Security Recommended" or
"Interoperability Recommended" columns would mean, or what data they
could contain (booleans? textual recommendations?), let alone how we
should populate them for the initial row.

I've opened a ticket to track this as:

https://gitlab.com/openpgp-wg/rfc4880bis/-/issues/17

> new registry" for those registries which were actually created by an older RFC

If you're talking about the Notation Flags registry, it doesn't
currently exist at IANA:

    https://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml

So yes, while the initial values that populate it came from the older,
obsoleted RFC, this RFC *is* the one that is creating the registry.

> some of those algorithms it shows as a MUST are optional at 9.1 / 9.3

Urgh, right, no matter what "elsewhere in this document" isn't helpful.
If there are particular sections, we should be referencing them
directly.  And the interactions between the profiles and whatever MTI
directives we land on seem unclear.

I've opened https://gitlab.com/openpgp-wg/rfc4880bis/-/issues/19 to try
to keep track of this.

> would they be interesting / needed.

Agreed, this is confusing in its new context.  I've opened
https://gitlab.com/openpgp-wg/rfc4880bis/-/issues/18 to make sure we
resolve that.

> so that the other two won't need renumbering on publication.

Good call, this is now:
https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/37

        --dkg

---

From: Daniel Kahn Gillmor <[email-masked]>
Date: Fri, 26 Feb 2021 23:52:23 -0500

> Would a MUST NOT use Simple S2K and MUST NOT use Salted S2K be better?

I'm not sure about this at all.  For example, consider a system that
knows that the string is high-entropy ("good key equivalent") -- should
they be prohibited from using Simple or Salted S2K?  Is this MUST really
an interoperability concern as §6 of RFC 2119 suggests?

Furthermore, if this guidance is applicable to private key storage and
S2K, shouldn't it show up in those sections as well, not just in the
Security Considerations section?

I've opened a ticket to track this:
https://gitlab.com/openpgp-wg/rfc4880bis/-/issues/20

I welcome proposals for how to fix it.

        --dkg

---

From: "brian m. carlson" <[email-masked]>
Date: Sat, 27 Feb 2021 23:14:25 +0000

> - Incorporated RFC 6637 (ECDSA and ECDH, using NIST curves)

I noticed for v5 fingerprints we hash only the left 20 octets in the
ECDH KDF:

  20 octets representing a recipient encryption subkey or a master
  key fingerprint, identifying the key material that is needed for
  the decryption.  For version 5 keys the 20 leftmost octets of the
  fingerprint are used.

Absent a compelling reason, I'd prefer to see the entire fingerprint
used.  It doesn't make sense to define a fingerprint that's 32 octets
and then truncate it to 20 octets in some cases.  At that point, we're
relying on the collision resistance of a different algorithm, not
SHA-256, and decreasing the security level to below 128 bits.

Note that if we do this, we'll need to update the text above and below
to reflect that the sizes are not invariant.
-- 
brian m. carlson (he/him or they/them)
Houston, Texas, US

---

From: "brian m. carlson" <[email-masked]>
Date: Sat, 27 Feb 2021 23:38:08 +0000

> - Incorporate Curve25519 for ECDH

Most of what's there looks fine (excepting the v5 fingerprint thing I
mentioned elsewhere).

I'm wondering, however, if there's consensus for adding Curve448 as well
for ECDH.  (I would be in favor of it.)  I don't have an OID for it, but
I believe RFC 8410 defines one, although that RFC defines a different
OID for Curve25519 than I see here in the spec.

The reason I ask is that in many implementations, of the NIST curves,
only P-256 is implemented in a constant-time manner, whereas Curve25519
and Curve448 are almost always implemented in a constant-time manner.
For example, Go has this problem.  That's in addition to the pervasive
questions about the selection of the parameters, which I want to
acknowledge as a concern many people have but don't want to debate
extensively.

It therefore makes sense to provide a curve that doesn't have those
limitations for those cases where users or specifications require a
security level of 192 bits or greater.
-- 
brian m. carlson (he/him or they/them)
Houston, Texas, US

---

From: Peter Gutmann <[email-masked]>
Date: Sun, 28 Feb 2021 03:46:06 +0000

Daniel Kahn Gillmor <[email-masked]> writes:

>I'm not sure about this at all.  For example, consider a system that knows
>that the string is high-entropy ("good key equivalent") -- should they be
>prohibited from using Simple or Salted S2K?  Is this MUST really an
>interoperability concern as §6 of RFC 2119 suggests?

Agreed, but it's a pretty simple fix:

  Where it's likely that a low-entropy secret is being employed, a compliant
  application SHOULD use [...]

Peter.

---

From: Paul Wouters <[email-masked]>
Date: Sun, 28 Feb 2021 12:09:28 -0500 (EST)

> I'm wondering, however, if there's consensus for adding Curve448 as well

That is being tracked by the WG chairs.

> and Curve448 are almost always implemented in a constant-time manner.

Is that a concern for openpgp ? openpgp is not an interactive protocol
where there is a server-client with possible MITM observing time spent?

Paul

---

From: Paul Wouters <[email-masked]>
Date: Sun, 28 Feb 2021 12:15:13 -0500 (EST)

> to reflect that the sizes are not invariant.

I think whether or not this change can still be made depends on what has
already been implemented. That is, are we describing what is already out
there, or is this something new. If it is new, than this issue is worth
getting consensus on.

Can implementors share some light on this?

Does anyone remember the origin of only using 20 octets and not all
octets?

Paul

---

From: "brian m. carlson" <[email-masked]>
Date: Sun, 28 Feb 2021 17:17:15 +0000

> That is being tracked by the WG chairs.

Great.

> where there is a server-client with possible MITM observing time spent?

People definitely do use OpenPGP for interactive uses where constant
time operations are relevant.  For example, when you create a commit by
editing a file on GitHub, that commit will be signed by GitHub's private
key, which is an online use.  This is hardly the only case where people
sign online.

We've also seen cases where people do encryption and decryption online,
such as by sending an encrypted message to an API and getting back an
error or not depending on whether the message could be successfully
decrypted.

I agree that these are not the typical uses of OpenPGP, but people
definitely do use it for online operations, and therefore, we need to
properly consider them when we secure the protocol.
-- 
brian m. carlson (he/him or they/them)
Houston, Texas, US

---

From: Paul Wouters <[email-masked]>
Date: Sun, 28 Feb 2021 13:08:01 -0500 (EST)

>> double quotes but using single quotes as in C seems better.

I agree with this. It would be better.

> tooling to behave differently for characters in the two different

If the single quotes are part of the regular text, wouldn't it just work?

> put two spaces between a period and the next sentence.

Which in itself is pretty archaic and shouldn't be done by default :)
(Althouh the unit fmt command also still defaults to this)

> them "Camellia in OpenPGP" and "Elliptic Curves in OpenPGP".

Seems reasonable. If no one objects over the next few days we will merge
it in.

>> I can come up with something.

Indeed, please do.

Thanks for the review, and thanks to dkg for filing the issues raised to
discuss later in the WG.

Paul

---

From: Paul Wouters <[email-masked]>
Date: Sun, 28 Feb 2021 13:12:09 -0500 (EST)

> be better to use s0 and s1 (s for "sum") so that it's clear that it

I like the idea of using s0 and s1.

> non-substantive/editorial changes like this.

Although please also comment on the list, so the editors can use that
to determine consensus, and importantly, any AD later on can read the
mail archive to verify any contentious consensus claim.

Paul

---

From: Paul Wouters <[email-masked]>
Date: Sun, 28 Feb 2021 13:19:35 -0500 (EST)

> key, which is an online use.  This is hardly the only case where people

While this is online, there is no negotiation to monitor where you can
learn anything based on timing, as you don't get errors back to do
timing on?

> error or not depending on whether the message could be successfully

This does seem to be a case where constant time matters. I was not
aware that openpgp was used in such ways.

> properly consider them when we secure the protocol.

Sure, although if Curve448 has passed CFRG review, and other IETF
protocols are using it as well, I would think the algorithm would
be safe to use? And that constant time implementations will happen?
Especially since those other protocols like TLS or IKE would be much
more sensitive to this?

Paul

---

From: "brian m. carlson" <[email-masked]>
Date: Sun, 28 Feb 2021 18:44:01 +0000

> learn anything based on timing, as you don't get errors back to do

True, but you can create arbitrary content to sign, so you can influence
the data used in the signature.  If, for example, signing a message
where some hash bits have value A consistently takes more or less time
than a message where some bits have value B, then that could probably
be easily leveraged to learn something about the private key.

So I think this is a case where we'd see a timing oracle based on time
to complete versus a timing oracle based on success or failure.

> Especially since those other protocols like TLS or IKE would be much

I believe Curve448 is presently considered secure and is expected to be
so for as long as quantum computers are not a threat, which is why CFRG
standardized it.  All implementations of Curve25519 and Curve448 that
I'm aware of are specifically designed to be constant time.

I agree that protocols which are always online like TLS are more likely
to be vulnerable to these attacks, but since most implementations of
OpenPGP are general purpose, it's hard to exclude them from online
usage.
-- 
brian m. carlson (he/him or they/them)
Houston, Texas, US

---

From: Ángel <[email-masked]>
Date: Sun, 28 Feb 2021 23:09:03 +0100

>   application SHOULD use [...]

I would suggest a didactic approach, something like
> Simple S2K and Salted S2K specifiers are not particularly secure 
> when used with a low-entropy secret, such as those typically provided
> by users, and implementations SHOULD avoid using these methods on
> encryption of both keys and messages.

Best regards

---

From: Ángel <[email-masked]>
Date: Mon, 01 Mar 2021 02:49:22 +0100

On 2021-02-26 at 23:00 -0500, Daniel Kahn Gillmor wrote:
> > I would prefer to see the new section "ECC Curve OID" as 9.5 instead of 9..2

I'm thinking that perhaps (d) we should not treat this as a registry at
all, but as an specification for how to produce the Curve OIDs from the
OID themselves (basically, the text below the table, as an spec).
Then make the table itself informational.
This could be kept at section 9 or moved to section 13.
This links with the point mentioned by Werner during the call that
implementing other curves is automatic as they are identified by their
OID.

PS: It would be good to include a note as well at 9.1 mentioning the
public key algorithms which depend on a Curve parameter: ECDH (18),
ECDSA (19) and -when added- EdDSA (22).

---

From: Ángel <[email-masked]>
Date: Mon, 01 Mar 2021 03:08:04 +0100

> obsoleted RFC, this RFC *is* the one that is creating the registry.

No. I'm talking about every section but the "Signature Notation Data Subpacket Notation Flags" :-)
The other sections of §10 were already created by 4880.

It's probably explained somewhere, although I don't find the exact answer.

I see however that 
https://www.rfc-editor.org/rfc/rfc8126.html#section-8 mentions IANA
registration info should be updated to the new RFC, so I guess the
answer is that instead of "This specification creates a registry" they
should all be "This specification becomes the reference for registry…"
or something along that line.

I have opened https://gitlab.com/openpgp-wg/rfc4880bis/-/issues/23 to track this.

Best regards

---

From: Ángel <[email-masked]>
Date: Mon, 01 Mar 2021 03:09:29 +0100

On 2021-02-26 at 23:00 -0500, Daniel Kahn Gillmor wrote:
> If you want to follow up on one or the other, i recommend referring
> to the specific issue or merge request in the subject of the mailing
> list thread, if one exists.
> 
> I encourage folks to do this kind of tracking/triage on the issues
> they raise on-list directly, it's quite a bit of work to make sure
> that all the points get tracked so they can be handled.

Thanks for that. Feel free to ask for patches. It seemed odd to simply
propose a MR without first presenting that to the wg. What I consider a
good phrasing may not be considered so by someone else. Or just come up
with a better one.
Not sure how to proceeds without flooding with mails or issues/MR or
everything. It's straightforward if everyone simply agrees, but for
things that get discussed, it would be easy to lose track of that, yes.

I'm replying here directly to some points, stripping unrelated pieces,
and splitting another two blocks as different threads.

Best regards

> (
> https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-02.html
> )
> I'm also not sure how much single vs double quotes matters here.  If
> you want to propose a fix we can discuss it though :)

Wow. That's even worse. I can't really see a difference here (they may
have a slightly different font, I'm not even sure about that, that'd be
barely noticeable). I guess that's completely different at your side.
I'm attaching a screenshot.
I see they get into <code> tags, so it could be just a matter of adding
CSS.

> -Dash-escaped cleartext is the ordinary cleartext where every line
> starting with a dash `-` (0x2D) is prefixed by the sequence dash `-`
> (0x2D) and space ` ` (0x20).
> +Dash-escaped cleartext is the ordinary cleartext where every line
> starting with a <u>-</u> is prefixed by the sequence <u>-</u> and <u>
> </u>.
> 
> Hopefully that is no less clear than before, and the rendering is
> more normalized without the backticks.

Are those underlines? It seems (semantically) strange. The solution of
Paul of simply putting literal ' seems better, although maybe there's a
way to get a better output for html. I should have a look at the source
and what kramdown-rfc is doing.

> https://mailarchive.ietf.org/arch/msg/xml2rfc/6V7C7l-zxg97jRqvuaq8r1QBQqw/

I have no problem with the nbsp, although manually looking for "Philip
R. Zimmerman" in reflow looks like a hack (although if someone deserves
to appear there it's him).
Instead of adding that for, I would change the preceding split not to
split for single letters:
>     # assume all sentences split with a period (.), and not ! or ?
>     # also, accept accidental breaks on abbreviations like John Q.
> Public
> -    sentences:List[str] = x.split('. ')
> +    sentences:List[str] = re.split("(?<! [A-Z])\. ", x)

Although with the nbsp, '. ' shouldn't match, anyway.

It's funny how many of these things turned out to be toolchain issues.
I'm not sure I would have been able to track them as you did.

> These aren't the full RFC names 

> (4880 itself is not "OpenPGP"),

I noticed :-)

> they're shorthand labels, but i agree that they should be normalized
> to be more readable.  I submitted the editorial suggestion

Good.

Best,
Ángel