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