From 8c00d63d527276b4e940c3a54922b7f5d8eaba73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Wed, 5 Jan 2022 10:33:30 -0500 Subject: [PATCH] feat: Add is_small_order_point, is_prime_subgroup_point In a nutshell, this offers an opt-in way of performing some public key checks relating to small order components, without having to pay an additional point decompression. In detail: Since https://github.com/dalek-cryptography/ed25519-dalek/commit/8dbaf9a8d249a24a5225a1247195d4135669f608, the `PublicKey` type is the performant way to carry public key material, with an eager check that the point is on curve. However, some applications which may like eager point decompression also need to check whether the point is small order, or even torsion-free: - aligning a discrepancy in verification between batch verification and iterated verification (see #115), - avoiding small subgroup confinement attacks in a DH, - ... `verify_strict` was introduced to offer an opt-in approach to some of this sort of scrutiny at the time the key is used, but cannot be performed eagerly, e.g. at the time of deserializing a public key. Rejecting small order keys (or worse non-torsion-free) keys on deserialization would have a performance impact. However, it's still desirable to have the option to do so long before the key is ever used for any actual cryptographic purpose (e.g. signature verification). In order to perform this sort of check, some code bases have taken to [re-implementing the check from the bytes representation of the key, which involves an additional decompression](https://github.com/diem/diem/blob/a290b0859a6152a5ffd6f85773a875f17334adac/crates/diem-crypto/src/ed25519.rs#L358-L386). The added functions of this PR allow the checks to be performed without additional decompression. --- src/public.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/public.rs b/src/public.rs index 342adf6..077c136 100644 --- a/src/public.rs +++ b/src/public.rs @@ -89,6 +89,16 @@ impl PublicKey { &(self.0).0 } + /// Check whether this key is represented by a point in a smaller torsion subgroup + pub fn is_small_order_point(&self) -> bool { + self.1.is_small_order() + } + + /// Check whether this key is represented by a point that is in a larger prime-order subgroup + pub fn is_prime_subgroup_point(&self) -> bool { + self.1.is_torsion_free() + } + /// Construct a `PublicKey` from a slice of bytes. /// /// # Warning