hopr_crypto_types/
utils.rs1use cipher::zeroize;
2use generic_array::{ArrayLength, GenericArray};
3use hopr_crypto_random::{Randomizable, random_array};
4use k256::{
5 AffinePoint, Secp256k1,
6 elliptic_curve::{
7 PrimeField,
8 hash2curve::{ExpandMsgXmd, GroupDigest},
9 point::NonIdentity,
10 },
11};
12use sha3::Sha3_256;
13use subtle::{Choice, ConstantTimeEq};
14use typenum::Unsigned;
15
16use crate::{
17 errors::{
18 CryptoError,
19 CryptoError::{CalculationError, InvalidInputValue, InvalidParameterSize},
20 },
21 prelude::{HalfKey, SecretKey},
22 types::PublicKey,
23};
24
25pub(crate) fn random_group_element() -> ([u8; 32], NonIdentity<AffinePoint>) {
28 let scalar = k256::NonZeroScalar::random(&mut hopr_crypto_random::rng());
30 let point =
31 PublicKey::from_privkey(&scalar.to_bytes()).expect("non-zero scalar cannot represent an invalid public key");
32 (scalar.to_bytes().into(), point.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
53#[allow(deprecated)] pub fn k256_scalar_from_bytes(bytes: &[u8]) -> crate::errors::Result<k256::Scalar> {
57 if bytes.len() == k256::elliptic_curve::FieldBytesSize::<Secp256k1>::to_usize() {
58 Option::from(k256::Scalar::from_repr(*k256::FieldBytes::from_slice(bytes))).ok_or(InvalidInputValue("bytes"))
59 } else {
60 Err(InvalidInputValue("bytes"))
61 }
62}
63
64pub fn sample_secp256k1_field_element(secret: &[u8], tag: &str) -> crate::errors::Result<HalfKey> {
71 if secret.len() >= SecretKey::LENGTH {
72 let scalar = Secp256k1::hash_to_scalar::<ExpandMsgXmd<Sha3_256>>(
73 &[secret],
74 &[b"secp256k1_XMD:SHA3-256_SSWU_RO_", tag.as_bytes()],
75 )
76 .map_err(|_| CalculationError)?;
77 Ok(HalfKey::try_from(scalar.to_bytes().as_ref())?)
78 } else {
79 Err(InvalidParameterSize {
80 name: "secret",
81 expected: SecretKey::LENGTH,
82 })
83 }
84}
85
86#[derive(Clone, zeroize::ZeroizeOnDrop)]
90pub struct SecretValue<L: ArrayLength>(GenericArray<u8, L>);
91
92impl<L: ArrayLength> ConstantTimeEq for SecretValue<L> {
93 fn ct_eq(&self, other: &Self) -> Choice {
94 self.0.ct_eq(&other.0)
95 }
96}
97
98impl<L: ArrayLength> AsRef<[u8]> for SecretValue<L> {
99 fn as_ref(&self) -> &[u8] {
100 self.0.as_ref()
101 }
102}
103
104impl<L: ArrayLength> From<GenericArray<u8, L>> for SecretValue<L> {
105 fn from(value: GenericArray<u8, L>) -> Self {
106 Self(value)
107 }
108}
109
110impl<'a, L: ArrayLength> From<&'a SecretValue<L>> for &'a GenericArray<u8, L> {
111 fn from(value: &'a SecretValue<L>) -> Self {
112 &value.0
113 }
114}
115
116impl<L: ArrayLength> TryFrom<&[u8]> for SecretValue<L> {
117 type Error = CryptoError;
118
119 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
120 if value.len() == Self::LENGTH {
121 Ok(Self(GenericArray::from_slice(value).clone()))
122 } else {
123 Err(InvalidInputValue("value"))
124 }
125 }
126}
127
128impl<L: ArrayLength> Default for SecretValue<L> {
129 fn default() -> Self {
130 Self(GenericArray::default())
131 }
132}
133
134impl<L: ArrayLength> AsMut<[u8]> for SecretValue<L> {
135 fn as_mut(&mut self) -> &mut [u8] {
136 self.0.as_mut()
137 }
138}
139
140impl<L: ArrayLength> From<SecretValue<L>> for Box<[u8]> {
141 fn from(value: SecretValue<L>) -> Self {
142 value.as_ref().into()
143 }
144}
145
146impl From<SecretValue<typenum::U32>> for [u8; 32] {
147 fn from(value: SecretValue<typenum::U32>) -> Self {
148 value.0.into_array()
149 }
150}
151
152#[cfg(feature = "serde")]
153impl<L: ArrayLength> serde::Serialize for SecretValue<L> {
154 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
155 where
156 S: serde::Serializer,
157 {
158 self.0.serialize(serializer)
159 }
160}
161
162#[cfg(feature = "serde")]
163impl<'de, L: ArrayLength> serde::Deserialize<'de> for SecretValue<L> {
164 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
165 where
166 D: serde::Deserializer<'de>,
167 {
168 Ok(Self(GenericArray::deserialize(deserializer)?))
169 }
170}
171
172impl<L: ArrayLength> SecretValue<L> {
173 pub const LENGTH: usize = L::USIZE;
175}
176
177impl<L: ArrayLength> Randomizable for SecretValue<L> {
178 fn random() -> Self {
180 Self(random_array())
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187
188 #[test]
189 fn test_sample_field_element() {
190 let secret = [1u8; SecretKey::LENGTH];
191 assert!(sample_secp256k1_field_element(&secret, "TEST_TAG").is_ok());
192 }
193}