hopr_crypto_types/
utils.rs1use crate::errors::CryptoError;
2use crate::errors::CryptoError::InvalidInputValue;
3use generic_array::{ArrayLength, GenericArray};
4use hopr_crypto_random::random_array;
5use k256::elliptic_curve::{Group, PrimeField};
6use subtle::{Choice, ConstantTimeEq};
7use zeroize::{Zeroize, ZeroizeOnDrop};
8
9pub fn xor_inplace(a: &mut [u8], b: &[u8]) {
11 let bound = a.len().min(b.len());
12
13 for i in 0..bound {
15 a[i] ^= b[i];
16 }
17}
18
19pub(crate) fn random_group_element() -> ([u8; 32], crate::types::CurvePoint) {
22 let mut scalar = k256::NonZeroScalar::from_uint(1u32.into()).unwrap();
23 let mut point = k256::ProjectivePoint::IDENTITY;
24 while point.is_identity().into() {
25 scalar = k256::NonZeroScalar::random(&mut hopr_crypto_random::rng());
26 point = k256::ProjectivePoint::GENERATOR * scalar.as_ref();
27 }
28 (scalar.to_bytes().into(), point.to_affine().into())
29}
30
31pub fn x25519_scalar_from_bytes(bytes: &[u8]) -> crate::errors::Result<curve25519_dalek::scalar::Scalar> {
35 if bytes.len() == 32 {
36 let mut clamped = [0u8; 32];
38 clamped.copy_from_slice(&bytes[..32]);
39 clamped[00] &= 0b1111_1000; clamped[31] &= 0b0111_1111; clamped[31] |= 0b0100_0000; Ok(curve25519_dalek::scalar::Scalar::from_bytes_mod_order(clamped))
44 } else {
45 Err(InvalidInputValue)
46 }
47}
48
49pub fn k256_scalar_from_bytes(bytes: &[u8]) -> crate::errors::Result<k256::Scalar> {
52 Option::from(k256::Scalar::from_repr(*k256::FieldBytes::from_slice(bytes))).ok_or(InvalidInputValue)
53}
54
55#[derive(Clone, Zeroize, ZeroizeOnDrop)]
59pub struct SecretValue<L: ArrayLength<u8>>(GenericArray<u8, L>);
60
61impl<L: ArrayLength<u8>> ConstantTimeEq for SecretValue<L> {
62 fn ct_eq(&self, other: &Self) -> Choice {
63 self.0.as_ref().ct_eq(other.0.as_ref())
64 }
65}
66
67impl<L: ArrayLength<u8>> AsRef<[u8]> for SecretValue<L> {
68 fn as_ref(&self) -> &[u8] {
69 self.0.as_ref()
70 }
71}
72
73impl<L: ArrayLength<u8>> From<GenericArray<u8, L>> for SecretValue<L> {
74 fn from(value: GenericArray<u8, L>) -> Self {
75 Self(value)
76 }
77}
78
79impl<'a, L: ArrayLength<u8>> From<&'a SecretValue<L>> for &'a GenericArray<u8, L> {
80 fn from(value: &'a SecretValue<L>) -> Self {
81 &value.0
82 }
83}
84
85impl<L: ArrayLength<u8>> TryFrom<&[u8]> for SecretValue<L> {
86 type Error = CryptoError;
87
88 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
89 if value.len() == Self::LENGTH {
90 Ok(Self(GenericArray::from_slice(value).clone()))
91 } else {
92 Err(InvalidInputValue)
93 }
94 }
95}
96
97impl<L: ArrayLength<u8>> Default for SecretValue<L> {
98 fn default() -> Self {
99 let mut ret = Self(GenericArray::default());
101 ret.zeroize();
102 ret
103 }
104}
105
106impl<L: ArrayLength<u8>> AsMut<[u8]> for SecretValue<L> {
107 fn as_mut(&mut self) -> &mut [u8] {
108 self.0.as_mut()
109 }
110}
111
112impl<L: ArrayLength<u8>> From<SecretValue<L>> for Box<[u8]> {
113 fn from(value: SecretValue<L>) -> Self {
114 value.as_ref().into()
115 }
116}
117
118impl<L: ArrayLength<u8>> SecretValue<L> {
119 pub const LENGTH: usize = L::USIZE;
121
122 pub fn random() -> Self {
124 Self(random_array())
125 }
126}