use crate::{
traits::ToMontgomery,
utils::{
crypto::key::{X25519PrivateKey, X25519PublicKey},
curve_point::Curve,
elliptic_curve::F25519,
},
};
use std::ops::Mul;
pub fn get_shared_secret<
Base: F25519,
S: Clone + Copy + Mul<C, Output = C>,
C: Curve + ToMontgomery<Output = Base>,
>(
private_key: X25519PrivateKey<S>,
public_key: X25519PublicKey<C>,
) -> Base {
(private_key.inner() * public_key.inner())
.to_montgomery(private_key.is_expected_non_zero && public_key.is_expected_non_identity)
.0
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
traits::FromLeBytes,
utils::{
curve_point::CurvePoint,
field::{BaseField, ScalarField},
},
};
#[test]
fn test_get_shared_secret() {
let test_data: [([u8; 32], [u8; 32], [u8; 32]); 5] = [
(
[
79, 199, 145, 114, 162, 100, 170, 63, 44, 63, 54, 126, 103, 170, 132, 78, 148,
119, 210, 52, 131, 103, 4, 118, 29, 247, 127, 235, 193, 80, 210, 170,
],
[
158, 160, 64, 24, 61, 192, 235, 182, 154, 139, 164, 90, 18, 208, 56, 146, 139,
75, 93, 101, 137, 165, 192, 12, 17, 86, 200, 18, 198, 178, 240, 167,
],
[
162, 54, 163, 41, 149, 202, 42, 90, 142, 151, 173, 221, 246, 59, 221, 212, 50,
131, 100, 215, 62, 152, 161, 156, 24, 145, 41, 94, 78, 213, 220, 5,
],
),
(
[
161, 37, 23, 231, 148, 32, 153, 52, 146, 96, 11, 87, 160, 246, 147, 250, 244,
93, 196, 71, 62, 156, 59, 25, 96, 172, 17, 20, 7, 25, 166, 7,
],
[
195, 183, 31, 207, 125, 170, 40, 206, 229, 207, 71, 59, 62, 240, 50, 205, 234,
18, 46, 226, 48, 55, 17, 227, 4, 215, 230, 111, 84, 161, 168, 115,
],
[
214, 213, 217, 33, 199, 22, 131, 58, 154, 123, 82, 200, 8, 121, 251, 107, 70,
40, 208, 37, 148, 147, 197, 157, 131, 214, 64, 169, 234, 121, 169, 3,
],
),
(
[
129, 29, 5, 16, 28, 94, 151, 184, 110, 29, 118, 134, 178, 157, 161, 188, 124,
82, 213, 3, 203, 251, 72, 58, 97, 105, 87, 153, 151, 100, 43, 28,
],
[
9, 232, 103, 151, 165, 10, 146, 245, 133, 34, 10, 25, 43, 223, 233, 194, 174,
27, 81, 163, 92, 19, 131, 90, 139, 108, 23, 71, 242, 211, 44, 130,
],
[
229, 25, 35, 30, 24, 145, 19, 180, 90, 119, 70, 40, 135, 172, 71, 169, 114,
138, 238, 35, 198, 28, 38, 211, 57, 33, 199, 35, 162, 80, 112, 16,
],
),
(
[
95, 213, 217, 35, 191, 161, 68, 159, 122, 218, 224, 170, 149, 48, 44, 218, 208,
194, 229, 113, 170, 212, 65, 63, 237, 199, 29, 47, 23, 74, 244, 104,
],
[
84, 21, 79, 162, 217, 201, 124, 72, 81, 246, 61, 169, 53, 183, 59, 165, 7, 117,
80, 168, 83, 193, 69, 45, 188, 64, 231, 1, 253, 241, 97, 252,
],
[
40, 190, 233, 251, 24, 75, 162, 200, 74, 159, 236, 45, 194, 89, 130, 176, 29,
68, 44, 124, 165, 14, 178, 6, 248, 219, 202, 227, 211, 49, 93, 32,
],
),
(
[
63, 110, 198, 241, 56, 96, 91, 151, 113, 158, 157, 78, 49, 204, 44, 176, 214,
124, 177, 199, 92, 1, 218, 184, 198, 53, 21, 32, 41, 44, 239, 131,
],
[
127, 198, 190, 15, 200, 200, 249, 10, 169, 254, 175, 102, 156, 106, 91, 116,
122, 84, 130, 63, 112, 25, 254, 7, 192, 80, 132, 209, 106, 114, 174, 101,
],
[
193, 45, 60, 220, 218, 245, 111, 88, 221, 57, 147, 206, 251, 168, 114, 149, 25,
46, 98, 199, 202, 220, 1, 236, 69, 88, 145, 90, 113, 19, 47, 122,
],
),
];
test_data
.into_iter()
.for_each(|(private_key_a_bytes, private_key_b_bytes, expected)| {
let private_key_a =
X25519PrivateKey::<ScalarField>::from_le_bytes(private_key_a_bytes);
let public_key_a =
X25519PublicKey::<CurvePoint>::new_from_private_key(private_key_a);
let private_key_b =
X25519PrivateKey::<ScalarField>::from_le_bytes(private_key_b_bytes);
let public_key_b =
X25519PublicKey::<CurvePoint>::new_from_private_key(private_key_b);
let shared_secret_a = get_shared_secret(private_key_a, public_key_b);
let shared_secret_b = get_shared_secret(private_key_b, public_key_a);
let expected = BaseField::from_le_bytes(expected);
assert_eq!(shared_secret_a, expected);
assert_eq!(shared_secret_b, expected);
});
}
}