[openpgp] Re: pure vs. pre-hash in FIPS 204 and 205

Falko Strenzke <falko.strenzke@mtg.de> Mon, 26 August 2024 11:25 UTC

Return-Path: <falko.strenzke@mtg.de>
X-Original-To: openpgp@ietfa.amsl.com
Delivered-To: openpgp@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 3770AC14CE29 for <openpgp@ietfa.amsl.com>; Mon, 26 Aug 2024 04:25:35 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.107
X-Spam-Level:
X-Spam-Status: No, score=-2.107 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01, URIBL_DBL_BLOCKED_OPENDNS=0.001, URIBL_ZEN_BLOCKED_OPENDNS=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=mtg.de
Received: from mail.ietf.org ([50.223.129.194]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id lVStsDiuyt5k for <openpgp@ietfa.amsl.com>; Mon, 26 Aug 2024 04:25:30 -0700 (PDT)
Received: from www.mtg.de (www.mtg.de [IPv6:2a02:b98:8:2::2]) (using TLSv1.3 with cipher TLS_CHACHA20_POLY1305_SHA256 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-256) server-digest SHA256) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 1F0D2C14F738 for <openpgp@ietf.org>; Mon, 26 Aug 2024 04:25:28 -0700 (PDT)
Received: from minka.mtg.de (minka [IPv6:2a02:b98:8:1:0:0:0:9]) by www.mtg.de (8.18.1/8.18.1) with ESMTPS id 47QBPOhC007049 (version=TLSv1.3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256 verify=NOT); Mon, 26 Aug 2024 13:25:24 +0200
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mtg.de; s=mail201801; t=1724671524; bh=8S3xF2UCGYwyS5+PqaKsbG2fDCHwN6Y0b1JRJRLfkFY=; h=Date:Subject:To:References:From:In-Reply-To; b=av1t/LzBpQbG6fQdtBRhwmmXt1tNgPsqy7k2Ir72HR8hG5UA6XIZxogyiOD9AtJj6 5nGN7wDP5X2Sqe9+CKHHZjLVK4lpNTFd8TsttYnNoHHrP5PZOkUi4GJi+0ayb4djLm 9Rcvp1m04keIiYMNZle1jYvHIQrS6ob49Wg/DD9E0ov0IIDy457IyEfWRsN0+q2u4S KVqf8Bg6L1YUEEmsMNoc1+WJiWCJy1XQW5DIK34ew7Ryz2+YV08KxydvGQnEnPhrbt FfQ5ApaSBSRGEq2vzGBbiPQkqGgC87f6Y5EqElNT+WZWzwyJZA8wh3Pyst2jbWp9gC 01Cyj7BS1fdlw==
Received: from [10.8.0.100] (vpn-10-8-0-100 [10.8.0.100]) by minka.mtg.de (8.18.1/8.18.1) with ESMTPS id 47QBPMd1026973 (version=TLSv1.3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256 verify=NOT); Mon, 26 Aug 2024 13:25:22 +0200
Message-ID: <5e4fd25f-3f2d-4263-a9f6-4370f308c90e@mtg.de>
Date: Mon, 26 Aug 2024 13:25:22 +0200
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird
To: Justus Winter <justus@sequoia-pgp.org>, "openpgp@ietf.org" <openpgp@ietf.org>
References: <fb9f748b-2024-4de1-849a-e52880c9a241@mtg.de> <87plpvwrcj.fsf@europ.lan>
Content-Language: en-GB
From: Falko Strenzke <falko.strenzke@mtg.de>
In-Reply-To: <87plpvwrcj.fsf@europ.lan>
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha-512"; boundary="------------ms080007020704070301000708"
Message-ID-Hash: N5PZGV5QJWUMSQZPYZACSZPGQYHXY6OS
X-Message-ID-Hash: N5PZGV5QJWUMSQZPYZACSZPGQYHXY6OS
X-MailFrom: falko.strenzke@mtg.de
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-openpgp.ietf.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header
X-Mailman-Version: 3.3.9rc4
Precedence: list
Subject: [openpgp] Re: pure vs. pre-hash in FIPS 204 and 205
List-Id: "Ongoing discussion of OpenPGP issues." <openpgp.ietf.org>
Archived-At: <https://mailarchive.ietf.org/arch/msg/openpgp/c70Km5WoLBQJjRaKuDKxrCdhOFU>
List-Archive: <https://mailarchive.ietf.org/arch/browse/openpgp>
List-Help: <mailto:openpgp-request@ietf.org?subject=help>
List-Owner: <mailto:openpgp-owner@ietf.org>
List-Post: <mailto:openpgp@ietf.org>
List-Subscribe: <mailto:openpgp-join@ietf.org>
List-Unsubscribe: <mailto:openpgp-leave@ietf.org>

I'll try to make clear where the misconception lies. This hopefully also 
answers Daniel's question in this regard. I'll give a (hopefully) 
consistent write up first, and further down I also give some inline 
comments to your message.

RFC 8032 specifies PureEdDSA and HashEdDSA. The latter is what I refer 
to as the pre-hash variant (and RFC 8032 with the formal internal name 
Ed25519ph, ph = "pre-hash"). I restrict the discussion to Ed25519, the 
case of Ed448 is analogous.

The two variants differ in how the message is processed and in the 
result of dom2(F, C).

The differences are that

- for PureEdDSA, we have dom2(F, C) = empty string and PH(M) = identity 
operation, i.e., no hashing happens before the signature operation,
- for HashEdDSA, we have F=1, dom2(F, C) is specified as an actual hash 
computation, and PH(M) is whatever hash function is used to pre-hash the 
message (i.e., typically being hashed on the protocol layer).

This means that for PureEdDSA, the message has to be input directly into 
the signature algorithm. If instead a hash of the message H(M) is input, 
then one specific advantage of the construction of EdDSA is missed, 
namely of not being vulnerable to general hash collision weaknesses in 
the underlying hash algorithms.

The quote from RFC 8032

The prehashing also makes the functions greatly more vulnerable to weaknesses in hash functions used. These variants SHOULD NOT be used.

of course applies to this very construction in RFC 9580, as there the 
hash of the message is input to the signing function, making it 
vulnerable to general collision weaknesses in the hash function used.

(From a security perspective, this is not relevant to v6 signatures due 
to the random salt in signatures, however. It fully applies to v4 
signatures, though).

To use PureEdDSA correctly, no hash of the message may be computed in 
the protocol. Instead, the full message would need to be input to the 
signature function. (I am not saying this should actually have been done 
in RFC 9580, as that doesn't seem to work well with OpenPGP.)

To put this very simple: when a specification of a signature scheme says 
"M" (the message), it is a security problem to replace it by "Hash(M)".

Accordingly, RFC 9580 is effectively using a pre-hash variant of EdDSA. 
However, differently than it is intended by RFC 8032. In order to do it 
compliant with RFC 8032, it would have to be done by using the HashEdDSA 
variant and providing the message hash from the protocol laver to the 
signature function as PH(M). By no means any double hashing occurs 
anywhere, as both you and Daniel have claimed. This probably the source 
of the misunderstanding, which happens when replacing the message M with 
Hash(M).

What theoretically results from the incorrect use of PureEdDSA to 
process a hash of the message, is a signature forgery vulnerability: If 
also correct use of PureEdDSA exists in parallel in a protocol, then it 
would be possible to exchange a message for its hash and still have 
valid signature. The internal domain separation of EdDSA is supposed to 
prevent this (quote from RFC 8032), but certainly requires that the 
message and a hash of it are never confused on the protocol layer:

    The schemes described in this document are designed to be resistant
    to mixing prehashes.  That is, it is infeasible to find a message
    that verifies using the same signature under another scheme, even if
    the original signed message was chosen.

As I wrote before, I don't think this problem really applies to OpenPGP, 
since if PureEdDSA with the message as direct input (i.e., correct use 
of PureEdDSA) should ever also be specified for OpenPGP, the scheme 
would receive a different algorithm ID. The algorithm ID then ensures 
the domain separation in OpenPGP's own digest computation.

Am 26.08.24 um 11:44 schrieb Justus Winter:
> Hi Falko :)
>
> Falko Strenzke<falko.strenzke@mtg.de> writes:
>
>> I attribute this at least in part to a misunderstanding about the
>> variants “pure” vs. “pre-hash” in RFC 8032 (EdDSA) as well as FIPS 204
>> and 205. The idea is to use the pre-hash variant whenever the message
>> is first hashed and then input to the signature algorithm. As I had
>> mentioned on this list as well, this is done – formally – wrong in RFC
>> 9580, which specifies to use the pure variant of EdDSA to sign the
>> hash of the message.
> I continue to be puzzled by this assertion, but I want to make another
> effort to understand it.
>
> RFC8032 defines two variants: PureEdDSA and HashEdDSA.  They differ in
> the prehash parameter:
>
>     11.  A "prehash" function PH.  PureEdDSA means EdDSA where PH is the
>          identity function, i.e., PH(M) = M.  HashEdDSA means EdDSA where
>          PH generates a short output, no matter how long the message is;
>          for example, PH(M) = SHA-512(M).
>
> I'm convinced that OpenPGP uses the PureEdDSA variant, i.e.:
>
>    sig = PureEdDSA(Hash(OpenPGP_Hash_Stream))
>                    ^ This happens in OpenPGP
>
> The evidence I have gathered for that is:
>
> - Sequoia useshttps://docs.rs/nettle/latest/nettle/ed25519/fn.sign.html
> - This primitive is tested against the test vectors from
>    https://datatracker.ietf.org/doc/html/rfc8032#ref-ED25519-TEST-VECTORS
> - These test vectors are part of the test vectors for "Ed25519"
>    https://datatracker.ietf.org/doc/html/rfc8032#section-7.1
> - Ed25519 is EdDSA instantiated with: [...]
>    |   PH(x)   | x (i.e., the identity function)                       |
>    https://datatracker.ietf.org/doc/html/rfc8032#section-5.1
> -> "Ed25519" is PureEdDSA
> -> Sequoia uses PureEdDSA
> - Sequoia's v6 implementation agrees with all the other v6
>    implementations when using Ed25519-based binding signatures and data
>    signatures
>    https://tests.sequoia-pgp.org/v6.html#Detached_Sign-Verify_roundtrip_with_minimal_key_from_RFC9580
> -> OpenPGP as specified in RFC9580 uses PureEdDSA
Yes, certainly, RFC 9580 is specifying to use PureEdDSA. Only that 
PureEdDSA requires the input of M, and doesn't allow Hash(M) as input.
>
> On the other hand, if OpenPGP were to use the HashEdDSA variant, we'd
> compute:
>
>    sig = PureEdDSA(PH(Hash(OpenPGP_Hash_Stream)))
>                       ^ This happens in OpenPGP
>                    ^ This is the prehash in HashEdDSA
>
> Which seems not ideal.
This is the point of the misunderstanding. There is no double hashing. 
PH(OpenPGP_Hash_Stream) is the only hash that happens.
>
> Concluding, I'm pretty sure that OpenPGP uses PureEdDSA.  Since there is
> obviously some confusion, maybe it is not about what we are doing but
> what we are calling it.
>
> - Are you saying since arguably OpenPGP does pre-hashing, the overall
>    construction looks more like HashEdDSA, and therefore we should have
>    called it that?
There is no choice calling it this or that, as RFC 8032 specifies 
exactly how each variant is built. As I tried to show above, what RFC 
9580 does, is an incorrect use of PureEdDSA, because prior hashing of 
the message leads to a security degradation.
>
> - There is no "pre-hash" variant defined in RFC8032, so maybe that is a
>    FIPS term and the confusion arises because of that?

pre-hash = HashEdDSA, as I mentioned above.

Best regards,
Falko

>
>
> Best,
> Justus
-- 

*MTG AG*
Dr. Falko Strenzke

Phone: +49 6151 8000 24
E-Mail: falko.strenzke@mtg.de
Web: mtg.de <https://www.mtg.de>

<https://www.linkedin.com/search/results/all/?fetchDeterministicClustersOnly=true&heroEntityKey=urn%3Ali%3Aorganization%3A13983133&keywords=mtg%20ag&origin=RICH_QUERY_SUGGESTION&position=0&searchId=d5bc71c3-97f7-4cae-83e7-e9e16d497dc2&sid=3S5&spellCorrectionEnabled=false> 

Follow us
------------------------------------------------------------------------
<https://360-german-security-alliance.de/> 
<https://www.itsa365.de/de-de/companies/m/mtg-ag>

MTG AG - Dolivostr. 11 - 64293 Darmstadt, Germany
Commercial register: HRB 8901
Register Court: Amtsgericht Darmstadt
Management Board: Jürgen Ruf (CEO), Tamer Kemeröz
Chairman of the Supervisory Board: Dr. Thomas Milde

This email may contain confidential and/or privileged information. If 
you are not the correct recipient or have received this email in error,
please inform the sender immediately and delete this email.Unauthorised 
copying or distribution of this email is not permitted.

Data protection information: Privacy policy 
<https://www.mtg.de/en/privacy-policy>