Re: [CFRG] Does OPRF/OPAQUE require full implementation of RFC 9380
Stefan Santesson <stefan@aaa-sec.com> Wed, 03 April 2024 22:02 UTC
Return-Path: <stefan@aaa-sec.com>
X-Original-To: cfrg@ietfa.amsl.com
Delivered-To: cfrg@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id AC863C14F680 for <cfrg@ietfa.amsl.com>; Wed, 3 Apr 2024 15:02:03 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.093
X-Spam-Level:
X-Spam-Status: No, score=-2.093 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, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_ZEN_BLOCKED_OPENDNS=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001, 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=aaa-sec.com
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 4jAQTZrQhwf6 for <cfrg@ietfa.amsl.com>; Wed, 3 Apr 2024 15:01:59 -0700 (PDT)
Received: from smtp.outgoing.loopia.se (smtp.outgoing.loopia.se [93.188.3.37]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id B8320C14F5F6 for <cfrg@irtf.org>; Wed, 3 Apr 2024 15:01:58 -0700 (PDT)
Received: from s807.loopia.se (localhost [127.0.0.1]) by s807.loopia.se (Postfix) with ESMTP id 723C6300B834 for <cfrg@irtf.org>; Thu, 4 Apr 2024 00:01:56 +0200 (CEST)
Received: from s979.loopia.se (unknown [172.22.191.6]) by s807.loopia.se (Postfix) with ESMTP id 621662E2EFCF; Thu, 4 Apr 2024 00:01:56 +0200 (CEST)
Received: from s898.loopia.se (unknown [172.22.191.6]) by s979.loopia.se (Postfix) with ESMTP id 5FDFF10BC346; Thu, 4 Apr 2024 00:01:56 +0200 (CEST)
X-Virus-Scanned: amavisd-new at amavis.loopia.se
Authentication-Results: s898.loopia.se (amavisd-new); dkim=pass (2048-bit key) header.d=aaa-sec.com
Received: from s934.loopia.se ([172.22.191.6]) by s898.loopia.se (s898.loopia.se [172.22.190.17]) (amavisd-new, port 10024) with UTF8LMTP id vcv1uWrv884b; Thu, 4 Apr 2024 00:01:55 +0200 (CEST)
X-Loopia-Auth: user
X-Loopia-User: mailstore2@aaa-sec.com
X-Loopia-Originating-IP: 90.228.170.155
Received: from [10.10.0.158] (unknown [90.228.170.155]) (Authenticated sender: mailstore2@aaa-sec.com) by s934.loopia.se (Postfix) with ESMTPSA id CF8177CEA3A; Thu, 4 Apr 2024 00:01:54 +0200 (CEST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aaa-sec.com; s=loopiadkim1707241022; t=1712181714; bh=TLg2J1fsqF/7lFLqFh3J98bObM2IdP5s3KnFbTCVmEk=; h=Date:Subject:From:To:Cc:References:In-Reply-To; b=HkClpWpcBD/H/FYqfWpWCvdEQCzHE/cLEgAGupeRytJfz4ayCRzJcWj9eIGSn+4Br +3sWPhZj589bSyxuHMwxfTB9+iC9+UNoDbiDf5AeaC/ysB5qg4nRuD7a/9eCwtv6G+ I+kF+jBIGTsNzszDtmMtzVpy0cz0Mam7L3KqCOJU6VZG8tScfFwnrasnzdyMsOY3YM TByDkYldXLhI7Yv4RMWRtJHeu2KDujdobBYOqd+VPB6glmzg9/oR47rpzaanxTReIP 4C9r6VMQeumjb/pZQaNpWmrzem0qeQJnlm/gfK2hUe3SQNrhfpvgeg/8Ovu+NhqbSw KExHQVSJ1cDBw==
Content-Type: multipart/alternative; boundary="------------RzYoRoNTjkSRkOG8ycMUAvof"
Message-ID: <4976080c-12eb-4bfe-8301-19fafb20661d@aaa-sec.com>
Date: Thu, 04 Apr 2024 00:01:54 +0200
MIME-Version: 1.0
User-Agent: Mozilla Thunderbird Beta
From: Stefan Santesson <stefan@aaa-sec.com>
To: Mike Hamburg <mike@shiftleft.org>
Cc: IRTF CFRG <cfrg@irtf.org>
References: <410a0800-78ff-422f-8ca3-5a0211478cbd@aaa-sec.com> <ZggHSDs5bRweThW5@localhost> <CAPC=aNUSTv=JtpkG71vhu25jgpVqzL5XS81543ntLMUuXcchqw@mail.gmail.com> <a5ec7b9e-62d3-4bd0-8bc9-ad23c9818e2b@aaa-sec.com> <739A462E-D02A-4B36-871E-19C282A09F90@shiftleft.org> <eb7dd447-adab-47cc-870a-51c31d4b42b4@aaa-sec.com>
Content-Language: sv-SE, en-GB
Autocrypt: addr=stefan@aaa-sec.com; keydata= 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 4831tbIM6eKC9gY3xUsE4vSV/CPdPKjV
Organization: 3xA Security AB
In-Reply-To: <eb7dd447-adab-47cc-870a-51c31d4b42b4@aaa-sec.com>
Archived-At: <https://mailarchive.ietf.org/arch/msg/cfrg/QjjZ0CeQAc3NEU-KXVFeST4j-FY>
Subject: Re: [CFRG] Does OPRF/OPAQUE require full implementation of RFC 9380
X-BeenThere: cfrg@irtf.org
X-Mailman-Version: 2.1.39
Precedence: list
List-Id: Crypto Forum Research Group <cfrg.irtf.org>
List-Unsubscribe: <https://mailman.irtf.org/mailman/options/cfrg>, <mailto:cfrg-request@irtf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/cfrg/>
List-Post: <mailto:cfrg@irtf.org>
List-Help: <mailto:cfrg-request@irtf.org?subject=help>
List-Subscribe: <https://mailman.irtf.org/mailman/listinfo/cfrg>, <mailto:cfrg-request@irtf.org?subject=subscribe>
X-List-Received-Date: Wed, 03 Apr 2024 22:02:03 -0000
I just have to post a correction. That experimental test I posted is not correct. There is no reason to reveal through the Y value if you succeeded on an odd or even attempt. The correct version of the algorithm we tested was: loop a fixed amount (e.g. 0 -> 64) { test and increment { compressed (y,x) = hkdf(hash(pw), counter) if (point(y,x) == valid) also test an invalid point if (point(y,x) != valid) also test a valid point } save first valid point } /Stefan On 2024-04-03 23:36, Stefan Santesson wrote: > > Mike, > > Thank you very much for this great answer. > > Yes, we were looking at that type of attacks where the knowledge of > the input scalar allows you to reconstruct multiple OPRF responses for > arbitrary input. > > However, in that analysis I didn't consider the client as the > adversary. But when you do, that attack is quite obvious and a good > reason not to go there! > > > I totally agree on the constant-time issue. We made some > experimenting, just for the fun of it, and we ended up in something > like this as our best attempt: > > > loop a fixed amount (e.g. 0 -> 64) { > > test and increment { > > x = hkdf(hash(pw), counter) > > y = counter % 2 == 0 ? 0x02 : 0x03 // compressed > > if (point(y,x) == valid) also test an invalid point > > if (point(y,x) != valid) also test a valid point > > } > > save first valid point > > } > > > This way we always make almost exactly the same amount of work. For > each iteration in the loop we test one valid point and one invalid point. > > But still I could detect statistically detectable difference over many > consecutive tests of different passwords. But to detect this you > needed quite some attempts. > > I don't think there is a way to make this perfect. But for simplistic > implementations where this is not an active threat, it does offer a > very easy implementation alternative. > > One we won't use of course ;) > > > Once you have hash to curve implemented, making it any other way makes > no sense. > > > Thanks again. This was very helpful! > > /Stefan > > > On 2024-04-03 17:39, Mike Hamburg wrote: >> Hello Stefan, >> >> Yes, I believe that if you used the Java code implementing >> >> NOPRF(x) := g^(hash(x) * k) >> >> then this would directly lead to a complete failure in the security >> goals of both OPRF and OPAQUE. (I’m calling it NOPRF because the >> problem is it’s not a PRF.) This is because one of OPRF’s security >> goals is that it cannot be evaluated offline without the server’s >> key, and this goal is violated for NOPRF once a single interaction >> has taken place (leading to the recovery of g^k). That goal is in >> turn required for OPAQUE; if the PRF were weak and could be evaluated >> offline, then a malicious client could brute-force the password >> offline after one interaction with the server. >> >> This is because, when using OPRF, the client’s first message commits >> to a guess of the password, and then the server’s first message gives >> enough information to check that guess. With NOPRF, the client's >> first message does not commit to a guess of the password, so the >> client can then use the server’s first message to check any guess >> (i.e. to brute-force the password offline). That said, while I have >> worked on similar PAKEs in the past, I have not studied the issue in >> detail for OPAQUE, so I might be missing something. >> >> >> Regarding “constant-time” behavior of try-and-increment, it is >> generally considered poor practice to try to plaster over >> non-constant-time behavior by setting min/max timers, because this >> usually doesn’t hide the timing as well as you want (the timers >> aren’t as precise as you want; the number of iterations still affects >> system load which affects timing of other tasks; etc). Best >> practices in this area require a more disciplined approach where >> secrets do not affect branches, memory addresses, arguments to >> certain instructions (such as division), etc. This difficulty was a >> significant part of the motivation for developing the existing >> hashToCurve methods: those methods were developed in order to be >> simpler to implement in constant time than try-and-increment. >> >> Unlike using NOPRF, having a non-constant-time hash won’t immediately >> and catastrophically break the system: it will be a meaningful >> vulnerability, but one which requires effort to exploit, instead of >> simply trying one login and then brute-forcing the password. Leaking >> even a small amount of information about a password (through timing) >> is a problem, because the whole point of PAKE is that passwords don’t >> have much entropy. >> >> Regards, >> — Mike >> >>> On Apr 2, 2024, at 2:36 AM, Stefan Santesson <stefan@aaa-sec.com> wrote: >>> >>> Thanks Jack, >>> >>> Your answer is very helpful. >>> >>> To clarify, my questions here are hypothetical questions to help >>> understand exactly where the boundaries are. My sample code is the >>> worst possible way to do it and nothing we plan to use. But I'm >>> still curious about whether it would work. >>> >>> I fully understand the problem of deriving a point from an input >>> scalar and I can see many situations where that would be >>> catastrophic. But AFAIK that catastrophic failure is as far as I >>> understand related to one of two events: >>> >>> 1) You actually do an operation with the input scalar as a private key >>> >>> 2) The derivation process can be reproduced by an adversary >>> >>> It seems to me that in OPRF neither of these are the case when a >>> password is hashed to a point and then blinded. Because of the >>> blinding, the point is never known and the input scalar is never used. >>> >>> That's why I'm curious if there is any explicit known threat here, >>> rather than this is considered good practice (which I fully agree with). >>> >>> >>> Regarding the "try-and-increment", I have also experimented with >>> constant time variants of this working simply like: >>> >>> - Make attempts and increment until you reached minimum constant >>> time, then take first successful result >>> >>> A variant of this is: >>> >>> - Find the first working point by "try-and-increment" and return >>> result after constant time has passed: >>> >>> The former seems better as it would require a more uniform workload, >>> but the precision of the constant time is better with the latter. >>> >>> >>> Again. Thanks for the replies. I personally plan to implement the >>> standard RFC9380, but these questions are helpful to internal >>> debates on whether you could do this simpler with a good security >>> result. >>> >>> /Stefan >>> >>> >>> >>> >>> On 2024-03-30 21:01, Jack Grigg wrote: >>>> Hi all, >>>> >>>> On Sat, Mar 30, 2024 at 6:56 AM Stefan Santesson >>>> <stefan@aaa-sec.com> wrote: >>>> >>>> Section 2.1 in OPR (RFC 9497) states: >>>> >>>> "HashToGroup(x): Deterministically maps an array of bytes x to >>>> an element of Group. The map must ensure that, for any >>>> adversary receiving R = HashToGroup(x), it is computationally >>>> difficult to reverse the mapping." >>>> >>>> [..] >>>> >>>> It continues to say that "Security properties of this function >>>> are described in [RFC9380]". >>>> >>>> [..] >>>> >>>> I would really appreciate help. Has this been discussed already >>>> to any detail. Is there any guidance available? >>>> >>>> As Mike Hamburg alludes to in another message in this thread, the >>>> security property of HashToGroup relied upon here is that the >>>> output of the function must be a uniformly random element of the >>>> group, with no easily-determined relation to any canonical >>>> generator of the group (more precisely, HashToGroup should be >>>> indifferentiable from a random oracle; see Sections 2.2.3 and 10.1 >>>> of RFC 9380). The proposed approach in your email makes inputScalar >>>> a known quantity, which directly breaks this property (inputScalar >>>> is the easily-determined relation to the canonical generator, >>>> because outputElement = [inputScalar] G). >>>> >>>> Regardless of RFC 9497 using "must" instead of "MUST" when >>>> describing it, its reliance on this security property is clear; see >>>> Sections 2.1, 4.6, and 7.2.1 of RFC 9497 for further details. >>>> >>>> If this is not good enough. Can you take any simpler path than >>>> full RFC 9380 implementation? >>>> >>>> If you use ristretto255 or decaf448, then most of the work should >>>> already be done by the libraries implementing the group (see >>>> below). See Section 4.1 of RFC 9497 for an OPRF ciphersuite >>>> instantiated over ristretto255 and SHA-512. >>>> >>>> For other groups (such as elliptic curves), there are other >>>> approaches like "try-and-increment", but these are not >>>> constant-time and may have other side-channel vulnerabilities in >>>> your setting; you would need to consult a cryptographer. >>>> >>>> On Sat, Mar 30, 2024 at 7:37 AM stef <f3o09vld@ctrlc.hu> wrote: >>>> >>>> tbh i also think this is overkill since for some groups, like >>>> ristretto255 for >>>> example there is a widely used hashtogroup available in most big >>>> implementations (like crypto_scalarmult_ed25519 and >>>> crypto_core_ristretto255_from_hash in libsodium). >>>> >>>> Just to clarify here for wider benefit: RFC 9496 (which specifies >>>> ristretto255, as well as decaf448) includes an Element Derivation >>>> function (in Section 4.3.4), which when paired with a hash function >>>> can be used to build a hash-to-group operation (which I believe is >>>> what library functions like crypto_core_ristretto255_from_hash in >>>> libsodium provide). Appendix B of RFC 9380 documents precisely how >>>> this should be done to be compatible with it (specifically using an >>>> expand_message function that conforms to Section 5.3 of RFC 9380). >>>> >>>> Cheers, >>>> Jack >>> _______________________________________________ >>> CFRG mailing list >>> CFRG@irtf.org >>> https://mailman.irtf.org/mailman/listinfo/cfrg >> > > _______________________________________________ > CFRG mailing list > CFRG@irtf.org > https://mailman.irtf.org/mailman/listinfo/cfrg
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Michael StJohns
- [CFRG] Does OPRF/OPAQUE require full implementati… Stefan Santesson
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… stef
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Stefan Santesson
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… stef
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Jack Grigg
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Mike Hamburg
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Stefan Santesson
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Mike Hamburg
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Stefan Santesson
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Stefan Santesson
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Stefan Santesson
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Hubert Kario
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Stefan Santesson
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Hubert Kario
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Stefan Santesson
- Re: [CFRG] Does OPRF/OPAQUE require full implemen… Sander Dijkhuis