hopr_crypto_types/
utils.rs1use crate::errors::CryptoError;
2use crate::errors::CryptoError::{CalculationError, InvalidInputValue, InvalidParameterSize};
3use crate::prelude::{HalfKey, SecretKey};
4use cipher::zeroize;
5use generic_array::{ArrayLength, GenericArray};
6use hopr_crypto_random::{random_array, Randomizable};
7use k256::elliptic_curve::hash2curve::{ExpandMsgXmd, GroupDigest};
8use k256::elliptic_curve::{Group, PrimeField};
9use k256::Secp256k1;
10use sha3::Sha3_256;
11use subtle::{Choice, ConstantTimeEq};
12use typenum::Unsigned;
13
14pub(crate) fn random_group_element() -> ([u8; 32], crate::types::CurvePoint) {
17 let mut scalar = k256::NonZeroScalar::from_uint(1u32.into()).unwrap();
18 let mut point = k256::ProjectivePoint::IDENTITY;
19 while point.is_identity().into() {
20 scalar = k256::NonZeroScalar::random(&mut hopr_crypto_random::rng());
21 point = k256::ProjectivePoint::GENERATOR * scalar.as_ref();
22 }
23 (scalar.to_bytes().into(), point.to_affine().into())
24}
25
26pub fn x25519_scalar_from_bytes(bytes: &[u8]) -> crate::errors::Result<curve25519_dalek::scalar::Scalar> {
30 if bytes.len() == 32 {
31 let mut clamped = [0u8; 32];
33 clamped.copy_from_slice(&bytes[..32]);
34 clamped[00] &= 0b1111_1000; clamped[31] &= 0b0111_1111; clamped[31] |= 0b0100_0000; Ok(curve25519_dalek::scalar::Scalar::from_bytes_mod_order(clamped))
39 } else {
40 Err(InvalidInputValue("bytes"))
41 }
42}
43
44pub fn k256_scalar_from_bytes(bytes: &[u8]) -> crate::errors::Result<k256::Scalar> {
47 if bytes.len() == k256::elliptic_curve::FieldBytesSize::<Secp256k1>::to_usize() {
48 Option::from(k256::Scalar::from_repr(*k256::FieldBytes::from_slice(bytes))).ok_or(InvalidInputValue("bytes"))
49 } else {
50 Err(InvalidInputValue("bytes"))
51 }
52}
53
54pub fn sample_secp256k1_field_element(secret: &[u8], tag: &str) -> crate::errors::Result<HalfKey> {
60 if secret.len() >= SecretKey::LENGTH {
61 let scalar = Secp256k1::hash_to_scalar::<ExpandMsgXmd<Sha3_256>>(
62 &[secret],
63 &[b"secp256k1_XMD:SHA3-256_SSWU_RO_", tag.as_bytes()],
64 )
65 .map_err(|_| CalculationError)?;
66 Ok(HalfKey::try_from(scalar.to_bytes().as_ref())?)
67 } else {
68 Err(InvalidParameterSize {
69 name: "secret",
70 expected: SecretKey::LENGTH,
71 })
72 }
73}
74
75#[derive(Clone, zeroize::ZeroizeOnDrop)]
79pub struct SecretValue<L: ArrayLength>(GenericArray<u8, L>);
80
81impl<L: ArrayLength> ConstantTimeEq for SecretValue<L> {
82 fn ct_eq(&self, other: &Self) -> Choice {
83 self.0.ct_eq(&other.0)
84 }
85}
86
87impl<L: ArrayLength> AsRef<[u8]> for SecretValue<L> {
88 fn as_ref(&self) -> &[u8] {
89 self.0.as_ref()
90 }
91}
92
93impl<L: ArrayLength> From<GenericArray<u8, L>> for SecretValue<L> {
94 fn from(value: GenericArray<u8, L>) -> Self {
95 Self(value)
96 }
97}
98
99impl<'a, L: ArrayLength> From<&'a SecretValue<L>> for &'a GenericArray<u8, L> {
100 fn from(value: &'a SecretValue<L>) -> Self {
101 &value.0
102 }
103}
104
105impl<L: ArrayLength> TryFrom<&[u8]> for SecretValue<L> {
106 type Error = CryptoError;
107
108 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
109 if value.len() == Self::LENGTH {
110 Ok(Self(GenericArray::from_slice(value).clone()))
111 } else {
112 Err(InvalidInputValue("value"))
113 }
114 }
115}
116
117impl<L: ArrayLength> Default for SecretValue<L> {
118 fn default() -> Self {
119 Self(GenericArray::default())
120 }
121}
122
123impl<L: ArrayLength> AsMut<[u8]> for SecretValue<L> {
124 fn as_mut(&mut self) -> &mut [u8] {
125 self.0.as_mut()
126 }
127}
128
129impl<L: ArrayLength> From<SecretValue<L>> for Box<[u8]> {
130 fn from(value: SecretValue<L>) -> Self {
131 value.as_ref().into()
132 }
133}
134
135#[cfg(feature = "serde")]
136impl<L: ArrayLength> serde::Serialize for SecretValue<L> {
137 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
138 where
139 S: serde::Serializer,
140 {
141 self.0.serialize(serializer)
142 }
143}
144
145#[cfg(feature = "serde")]
146impl<'de, L: ArrayLength> serde::Deserialize<'de> for SecretValue<L> {
147 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
148 where
149 D: serde::Deserializer<'de>,
150 {
151 Ok(Self(GenericArray::deserialize(deserializer)?))
152 }
153}
154
155impl<L: ArrayLength> SecretValue<L> {
156 pub const LENGTH: usize = L::USIZE;
158}
159
160impl<L: ArrayLength> Randomizable for SecretValue<L> {
161 fn random() -> Self {
163 Self(random_array())
164 }
165}