Skip to main content

generic_ecies/
common.rs

1#[cfg(feature = "curve-ed25519")]
2impl<S> crate::PrivateKey<S>
3where
4    S: crate::Suite<E = generic_ec::curves::Ed25519>,
5{
6    /// Since eddsa secret key is not a scalar, and most tools that call
7    /// themselves ed25519 are actually eddsa, we need to convert from eddsa key
8    /// to a scalar.
9    ///
10    /// Returns `None` if the bytes hash to zero (this has a vanishing
11    /// probability of occuring)
12    pub fn from_eddsa_pkey_bytes(bytes: &[u8; 32]) -> Option<Self> {
13        use sha2::Digest as _;
14        let scalar_bytes = sha2::Sha512::new().chain_update(bytes).finalize();
15        let mut scalar_bytes = zeroize::Zeroizing::<[u8; 64]>::new(scalar_bytes.into());
16        let scalar_bytes = &mut scalar_bytes[0..32];
17
18        // The lowest three bits of the first octet are cleared
19        scalar_bytes[0] &= 0b1111_1000;
20        // the highest bit of the last octet is cleared
21        scalar_bytes[31] &= 0b0111_1111;
22        // and the second highest bit of the last octet is set
23        scalar_bytes[31] |= 0b0100_0000;
24
25        let mut scalar = generic_ec::Scalar::<generic_ec::curves::Ed25519>::from_le_bytes_mod_order(
26            scalar_bytes,
27        );
28        let scalar = generic_ec::SecretScalar::new(&mut scalar);
29        let scalar =
30            generic_ec::NonZero::<generic_ec::SecretScalar<generic_ec::curves::Ed25519>>::try_from(
31                scalar,
32            )
33            .ok()?;
34        Some(Self { scalar })
35    }
36}
37
38#[cfg(test)]
39macro_rules! make_tests {
40    ($specific_tests:tt) => {
41        mod common_test {
42            use std::ops::Deref as _;
43            type E = <super::S as crate::Suite>::E;
44
45            #[test]
46            fn encrypt_decrypt() {
47                let mut rng = rand_dev::DevRng::new();
48                let key = super::PrivateKey::generate(&mut rng);
49                let pubkey = key.public_key();
50
51                let original_message = {
52                    let mut bytes = vec![0u8; 1337];
53                    rand_core::RngCore::fill_bytes(&mut rng, &mut bytes);
54                    bytes
55                };
56
57                let mut encrypted_message = pubkey.encrypt(&original_message, &mut rng).unwrap();
58
59                let parsed_message =
60                    super::EncryptedMessage::from_bytes(&mut encrypted_message).unwrap();
61                let decrypted_message = key.decrypt_in_place(parsed_message).unwrap();
62
63                assert_eq!(original_message, decrypted_message);
64            }
65
66            #[test]
67            fn message_encode() {
68                let mut rng = rand_dev::DevRng::new();
69
70                let ephemeral_key = generic_ec::Point::generator()
71                    * generic_ec::NonZero::<generic_ec::Scalar<E>>::random(&mut rng);
72                let mut message = [0u8; 322];
73                rand_core::RngCore::fill_bytes(&mut rng, &mut message);
74                let mut tag =
75                    cipher::generic_array::GenericArray::<u8, crate::MacSize<super::S>>::default();
76                rand_core::RngCore::fill_bytes(&mut rng, &mut tag);
77
78                let message = super::EncryptedMessage {
79                    ephemeral_key,
80                    message: &mut message,
81                    tag,
82                };
83                let mut message_bytes = message.to_bytes();
84                let restored = super::EncryptedMessage::from_bytes(&mut message_bytes).unwrap();
85                assert_eq!(message, restored);
86            }
87
88            #[test]
89            fn key_encode() {
90                let mut rng = rand_dev::DevRng::new();
91
92                let key = super::PrivateKey::generate(&mut rng);
93                let key_bytes = key.to_bytes();
94                let key_ = super::PrivateKey::from_bytes(&key_bytes).unwrap();
95                assert_eq!(key.scalar.deref().as_ref(), key_.scalar.deref().as_ref());
96
97                let pubkey = key.public_key();
98                let key_bytes = pubkey.to_bytes();
99                let pubkey_ = super::PublicKey::from_bytes(&key_bytes).unwrap();
100                assert_eq!(pubkey, pubkey_);
101            }
102
103            #[test]
104            fn from_bytes_too_short() {
105                let point = generic_ec::Point::<E>::generator().to_point();
106                let tag =
107                    cipher::generic_array::GenericArray::<u8, crate::MacSize<super::S>>::default();
108
109                // Test with compressed point: point ++ zero_tag
110                let mut buf = point.to_bytes(true).to_vec();
111                let compressed_len = buf.len();
112                buf.extend_from_slice(&tag);
113                for i in 0..buf.len() {
114                    let result = super::EncryptedMessage::from_bytes(&mut buf[..i]);
115                    assert!(
116                        matches!(result, Err(crate::DeserializeError::TooShort)),
117                        "expected TooShort for compressed input length {i}, got {result:?}",
118                    );
119                }
120
121                // Test with uncompressed point: point ++ zero_tag
122                let mut buf = point.to_bytes(false).to_vec();
123                buf.extend_from_slice(&tag);
124                for i in compressed_len..buf.len() {
125                    let result = super::EncryptedMessage::from_bytes(&mut buf[..i]);
126                    assert!(
127                        matches!(result, Err(crate::DeserializeError::TooShort)),
128                        "expected TooShort for uncompressed input length {i}, got {result:?}",
129                    );
130                }
131            }
132
133            internal_make_specific_tests!($specific_tests);
134        }
135    };
136}
137#[cfg(test)]
138pub(crate) use make_tests;
139
140#[cfg(test)]
141macro_rules! internal_make_specific_tests {
142    ("stream") => {
143        #[test]
144        fn encrypt_decrypt_inplace_ornot() {
145            let mut rng = rand_dev::DevRng::new();
146            let key = super::PrivateKey::generate(&mut rng);
147            let pubkey = key.public_key();
148
149            let mut bytes = vec![0u8; 1337];
150            rand_core::RngCore::fill_bytes(&mut rng, &mut bytes);
151            let original = bytes.clone();
152
153            let mut encrypted = pubkey.encrypt(&bytes, &mut rng.clone()).unwrap();
154            let encrypted_ = pubkey
155                .encrypt_in_place(&mut bytes, &mut rng)
156                .unwrap()
157                .to_bytes();
158
159            assert_eq!(encrypted, encrypted_);
160
161            let encrypted = super::EncryptedMessage::from_bytes(&mut encrypted).unwrap();
162            let decrypted = key.decrypt(&encrypted).unwrap();
163            let decrypted_ = key.decrypt_in_place(encrypted).unwrap();
164            assert_eq!(decrypted_, decrypted);
165            assert_eq!(original, decrypted);
166        }
167    };
168    ("block") => {
169        #[test]
170        fn encrypt_decrypt_inplace_ornot() {
171            let mut rng = rand_dev::DevRng::new();
172            let key = super::PrivateKey::generate(&mut rng);
173            let pubkey = key.public_key();
174
175            let mut bytes = vec![0u8; 1337];
176            rand_core::RngCore::fill_bytes(&mut rng, &mut bytes);
177            let original = bytes.clone();
178
179            let mut encrypted = pubkey.encrypt(&bytes, &mut rng.clone()).unwrap();
180
181            let size_with_pad = bytes.len() + crate::pad_size::<super::S>(bytes.len());
182            bytes.resize(size_with_pad, 0);
183            let encrypted_ = pubkey
184                .encrypt_in_place(&mut bytes, original.len(), &mut rng)
185                .unwrap()
186                .to_bytes();
187
188            assert_eq!(encrypted, encrypted_);
189
190            let encrypted = super::EncryptedMessage::from_bytes(&mut encrypted).unwrap();
191            let decrypted = key.decrypt(&encrypted).unwrap();
192            let decrypted_ = key.decrypt_in_place(encrypted).unwrap();
193            assert_eq!(decrypted_, decrypted);
194            assert_eq!(original, decrypted);
195        }
196    };
197    ($($_:tt)*) => {
198        compile_error!("make_tests! macro only supports \"block\" and \"stream\" parameters");
199    };
200}