dalek_ff_group/
ciphersuite.rs

1use zeroize::Zeroize;
2
3use sha2::{Digest, Sha512};
4
5use group::Group;
6use crate::Scalar;
7
8use ciphersuite::Ciphersuite;
9
10macro_rules! dalek_curve {
11  (
12    $feature: literal,
13
14    $Ciphersuite: ident,
15    $Point:       ident,
16    $ID:          literal
17  ) => {
18    use crate::$Point;
19
20    impl Ciphersuite for $Ciphersuite {
21      type F = Scalar;
22      type G = $Point;
23      type H = Sha512;
24
25      const ID: &'static [u8] = $ID;
26
27      fn generator() -> Self::G {
28        $Point::generator()
29      }
30
31      fn hash_to_F(dst: &[u8], data: &[u8]) -> Self::F {
32        Scalar::from_hash(Sha512::new_with_prefix(&[dst, data].concat()))
33      }
34    }
35  };
36}
37
38/// Ciphersuite for Ristretto.
39///
40/// hash_to_F is implemented with a naive concatenation of the dst and data, allowing transposition
41/// between the two. This means `dst: b"abc", data: b"def"`, will produce the same scalar as
42/// `dst: "abcdef", data: b""`. Please use carefully, not letting dsts be substrings of each other.
43#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
44pub struct Ristretto;
45dalek_curve!("ristretto", Ristretto, RistrettoPoint, b"ristretto");
46#[test]
47fn test_ristretto() {
48  ff_group_tests::group::test_prime_group_bits::<_, RistrettoPoint>(&mut rand_core::OsRng);
49
50  assert_eq!(
51    Ristretto::hash_to_F(
52      b"FROST-RISTRETTO255-SHA512-v11nonce",
53      &hex::decode(
54        "\
5581800157bb554f299fe0b6bd658e4c4591d74168b5177bf55e8dceed59dc80c7\
565c3430d391552f6e60ecdc093ff9f6f4488756aa6cebdbad75a768010b8f830e"
57      )
58      .unwrap()
59    )
60    .to_bytes()
61    .as_ref(),
62    &hex::decode("40f58e8df202b21c94f826e76e4647efdb0ea3ca7ae7e3689bc0cbe2e2f6660c").unwrap()
63  );
64}
65
66/// Ciphersuite for Ed25519, inspired by RFC-8032.
67///
68/// hash_to_F is implemented with a naive concatenation of the dst and data, allowing transposition
69/// between the two. This means `dst: b"abc", data: b"def"`, will produce the same scalar as
70/// `dst: "abcdef", data: b""`. Please use carefully, not letting dsts be substrings of each other.
71#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
72pub struct Ed25519;
73dalek_curve!("ed25519", Ed25519, EdwardsPoint, b"edwards25519");
74#[test]
75fn test_ed25519() {
76  ff_group_tests::group::test_prime_group_bits::<_, EdwardsPoint>(&mut rand_core::OsRng);
77
78  // Ideally, a test vector from RFC-8032 (not FROST) would be here
79  // Unfortunately, the IETF draft doesn't provide any vectors for the derived challenges
80  assert_eq!(
81    Ed25519::hash_to_F(
82      b"FROST-ED25519-SHA512-v11nonce",
83      &hex::decode(
84        "\
859d06a6381c7a4493929761a73692776772b274236fb5cfcc7d1b48ac3a9c249f\
86929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509"
87      )
88      .unwrap()
89    )
90    .to_bytes()
91    .as_ref(),
92    &hex::decode("70652da3e8d7533a0e4b9e9104f01b48c396b5b553717784ed8d05c6a36b9609").unwrap()
93  );
94}