Skip to content

Commit a6fb86a

Browse files
committed
Use constant generics
1 parent e5448fb commit a6fb86a

File tree

11 files changed

+156
-163
lines changed

11 files changed

+156
-163
lines changed

Cargo.lock

Lines changed: 2 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ path = "src/lib.rs"
1515
aes = "0.8"
1616
aes-gcm = "0.9"
1717
curve25519-dalek = "3.2"
18-
generic-array = { version = "0.14.5", features = ["serde"] }
1918
# specify the js feature for the WASM target
2019
getrandom = { version = "0.2", features = ["js"] }
2120
hex = "0.4"

src/asymmetric_crypto.rs

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use curve25519_dalek::{
1111
ristretto::{CompressedRistretto, RistrettoPoint},
1212
scalar::Scalar,
1313
};
14-
use generic_array::{typenum::U32, GenericArray};
1514
use rand_core::{CryptoRng, RngCore};
1615
use serde::{Deserialize, Serialize};
1716
use std::{
@@ -21,6 +20,12 @@ use std::{
2120
};
2221
use zeroize::{Zeroize, ZeroizeOnDrop};
2322

23+
/// X25519 secret key length
24+
const X25519_SK_LENGTH: usize = 32;
25+
26+
/// X25519 public key length
27+
const X25519_PK_LENGTH: usize = 32;
28+
2429
/// Asymmetric private key based on Curve25519.
2530
///
2631
/// Internally, a curve scalar is used. It is 128-bits long.
@@ -52,25 +57,22 @@ impl X25519PrivateKey {
5257
}
5358
}
5459

55-
impl KeyTrait for X25519PrivateKey {
56-
type Length = U32;
57-
58-
/// Convert the given private key into bytes.
59-
#[inline]
60-
#[must_use]
61-
fn to_bytes(&self) -> GenericArray<u8, Self::Length> {
62-
GenericArray::<u8, Self::Length>::from(self.0.to_bytes())
60+
impl KeyTrait<X25519_SK_LENGTH> for X25519PrivateKey {
61+
/// Converts the given key into bytes.
62+
fn to_bytes(&self) -> [u8; Self::LENGTH] {
63+
self.0.to_bytes()
6364
}
6465

66+
/// Converts the given bytes into key.
6567
fn try_from_bytes(bytes: &[u8]) -> Result<Self, CryptoCoreError> {
6668
Self::try_from(bytes)
6769
}
6870
}
6971

70-
impl TryFrom<[u8; 32]> for X25519PrivateKey {
72+
impl TryFrom<[u8; Self::LENGTH]> for X25519PrivateKey {
7173
type Error = CryptoCoreError;
7274

73-
fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
75+
fn try_from(bytes: [u8; Self::LENGTH]) -> Result<Self, Self::Error> {
7476
let scalar = Scalar::from_canonical_bytes(bytes).ok_or_else(|| {
7577
Self::Error::ConversionError(
7678
"Given bytes do not represent a canonical Scalar!".to_string(),
@@ -84,7 +86,7 @@ impl TryFrom<&[u8]> for X25519PrivateKey {
8486
type Error = CryptoCoreError;
8587

8688
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
87-
let bytes: [u8; 32] = bytes.try_into().map_err(|e| {
89+
let bytes: [u8; Self::LENGTH] = bytes.try_into().map_err(|e| {
8890
Self::Error::ConversionError(format!(
8991
"Error while converting slice of size {} to `X25519PublicKey`: {}",
9092
bytes.len(),
@@ -95,15 +97,9 @@ impl TryFrom<&[u8]> for X25519PrivateKey {
9597
}
9698
}
9799

98-
impl From<&X25519PrivateKey> for [u8; 32] {
99-
fn from(key: &X25519PrivateKey) -> Self {
100-
key.0.to_bytes()
101-
}
102-
}
103-
104100
// Needed by serde to derive `Deserialize`. Do not use otherwise since there
105101
// is a copy anyway
106-
impl From<X25519PrivateKey> for [u8; 32] {
102+
impl From<X25519PrivateKey> for [u8; X25519_SK_LENGTH] {
107103
fn from(key: X25519PrivateKey) -> Self {
108104
key.0.to_bytes()
109105
}
@@ -240,14 +236,11 @@ impl X25519PublicKey {
240236
}
241237
}
242238

243-
impl KeyTrait for X25519PublicKey {
244-
type Length = U32;
245-
246-
/// Convert the given public key into an array of bytes.
239+
impl KeyTrait<X25519_PK_LENGTH> for X25519PublicKey {
240+
/// Converts the given public key into an array of bytes.
247241
#[inline]
248-
#[must_use]
249-
fn to_bytes(&self) -> GenericArray<u8, Self::Length> {
250-
GenericArray::<u8, Self::Length>::from(self.0.compress().to_bytes())
242+
fn to_bytes(&self) -> [u8; Self::LENGTH] {
243+
self.0.compress().to_bytes()
251244
}
252245

253246
fn try_from_bytes(bytes: &[u8]) -> Result<Self, CryptoCoreError> {
@@ -261,10 +254,10 @@ impl From<&X25519PrivateKey> for X25519PublicKey {
261254
}
262255
}
263256

264-
impl TryFrom<[u8; 32]> for X25519PublicKey {
257+
impl TryFrom<[u8; Self::LENGTH]> for X25519PublicKey {
265258
type Error = CryptoCoreError;
266259

267-
fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
260+
fn try_from(bytes: [u8; Self::LENGTH]) -> Result<Self, Self::Error> {
268261
Ok(Self(CompressedRistretto(bytes).decompress().ok_or_else(
269262
|| {
270263
CryptoCoreError::ConversionError(
@@ -279,7 +272,7 @@ impl TryFrom<&[u8]> for X25519PublicKey {
279272
type Error = CryptoCoreError;
280273

281274
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
282-
let bytes: [u8; 32] = bytes.try_into().map_err(|e| {
275+
let bytes: [u8; Self::LENGTH] = bytes.try_into().map_err(|e| {
283276
Self::Error::ConversionError(format!(
284277
"Error while converting slice of size {} to `X25519PublicKey`: {}",
285278
bytes.len(),
@@ -292,13 +285,13 @@ impl TryFrom<&[u8]> for X25519PublicKey {
292285

293286
// Needed by serde to derive `Deserialize`. Do not use otherwise since there
294287
// is a copy anyway.
295-
impl From<X25519PublicKey> for [u8; 32] {
288+
impl From<X25519PublicKey> for [u8; X25519_PK_LENGTH] {
296289
fn from(key: X25519PublicKey) -> Self {
297290
key.0.compress().to_bytes()
298291
}
299292
}
300293

301-
impl From<&X25519PublicKey> for [u8; 32] {
294+
impl From<&X25519PublicKey> for [u8; X25519_PK_LENGTH] {
302295
fn from(key: &X25519PublicKey) -> Self {
303296
key.0.compress().to_bytes()
304297
}
@@ -379,15 +372,18 @@ impl ZeroizeOnDrop for X25519PublicKey {}
379372
#[cfg(test)]
380373
mod test {
381374
use crate::{
382-
asymmetric_crypto::{X25519PrivateKey, X25519PublicKey},
375+
asymmetric_crypto::{
376+
X25519PrivateKey, X25519PublicKey, X25519_PK_LENGTH, X25519_SK_LENGTH,
377+
},
383378
entropy::CsRng,
379+
KeyTrait,
384380
};
385381

386382
#[test]
387383
fn test_private_key_serialization() {
388384
let mut rng = CsRng::new();
389385
let sk = X25519PrivateKey::new(&mut rng);
390-
let bytes: [u8; 32] = (&sk).into();
386+
let bytes: [u8; X25519_SK_LENGTH] = sk.to_bytes();
391387
let recovered = X25519PrivateKey::try_from(bytes).unwrap();
392388
assert_eq!(sk, recovered);
393389
}
@@ -396,7 +392,7 @@ mod test {
396392
fn test_public_key_serialization() {
397393
let mut rng = CsRng::new();
398394
let pk = X25519PublicKey::new(&mut rng);
399-
let bytes: [u8; 32] = (&pk).into();
395+
let bytes: [u8; X25519_PK_LENGTH] = pk.to_bytes();
400396
let recovered = super::X25519PublicKey::try_from(bytes).unwrap();
401397
assert_eq!(pk, recovered);
402398
}

src/entropy.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use generic_array::{ArrayLength, GenericArray};
21
use rand_core::{CryptoRng, RngCore, SeedableRng};
32
use rand_hc::Hc128Rng;
43

@@ -21,8 +20,8 @@ impl CsRng {
2120
/// Generate a vector of random bytes with the given length.
2221
///
2322
/// - `len` : number of random bytes to generate
24-
pub fn generate_random_bytes<N: ArrayLength<u8>>(&mut self) -> GenericArray<u8, N> {
25-
let mut bytes = GenericArray::<u8, N>::default();
23+
pub fn generate_random_bytes<const LENGTH: usize>(&mut self) -> [u8; LENGTH] {
24+
let mut bytes = [0; LENGTH];
2625
self.rng.fill_bytes(&mut bytes);
2726
bytes
2827
}
@@ -58,16 +57,15 @@ impl CryptoRng for CsRng {}
5857
mod test {
5958

6059
use crate::entropy::CsRng;
61-
use generic_array::typenum::{Unsigned, U1024};
6260

6361
#[test]
6462
fn test_random_bytes() {
6563
let mut cs_rng = CsRng::default();
66-
type N = U1024;
64+
const N: usize = 1024;
6765
let random_bytes_1 = cs_rng.generate_random_bytes::<N>();
68-
assert_eq!(<N as Unsigned>::to_usize(), random_bytes_1.len());
66+
assert_eq!(N, random_bytes_1.len());
6967
let random_bytes_2 = cs_rng.generate_random_bytes();
70-
assert_eq!(<N as Unsigned>::to_usize(), random_bytes_1.len());
68+
assert_eq!(N, random_bytes_1.len());
7169
assert_ne!(random_bytes_1, random_bytes_2);
7270
}
7371
}

src/kdf.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::CryptoCoreError;
2-
use generic_array::{ArrayLength, GenericArray};
32
use hkdf::Hkdf;
43
use sha2::Sha256;
54

@@ -9,18 +8,18 @@ use sha2::Sha256;
98
///
109
/// - `bytes` : input bytes to hash, should be at least 32-bytes long
1110
/// - `info` : some optional additional information to use in the hash
12-
pub fn hkdf_256<KeyLength: ArrayLength<u8>>(
11+
pub fn hkdf_256<const LENGTH: usize>(
1312
bytes: &[u8],
1413
info: &[u8],
15-
) -> Result<GenericArray<u8, KeyLength>, CryptoCoreError> {
14+
) -> Result<[u8; LENGTH], CryptoCoreError> {
1615
if bytes.len() < 32 {
1716
return Err(CryptoCoreError::InvalidSize(
18-
"Input `bytes` size should be at least 32".to_string(),
17+
"Input `bytes` size should be at least 32 bytes".to_string(),
1918
));
2019
}
2120
let h = Hkdf::<Sha256>::new(None, bytes);
22-
let mut out = GenericArray::<u8, KeyLength>::default();
21+
let mut out = [0; LENGTH];
2322
h.expand(info, &mut out)
24-
.map_err(|_| CryptoCoreError::KdfError(KeyLength::to_usize()))?;
23+
.map_err(|_| CryptoCoreError::KdfError(LENGTH))?;
2524
Ok(out)
2625
}

src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,20 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
2323
pub use crate::error::CryptoCoreError;
2424

2525
pub mod reexport {
26-
pub use generic_array;
2726
// reexport `rand_core` so that the PRNG implement the correct version of the traits
2827
pub use rand_core;
2928
}
3029

3130
/// Trait defining a cryptographic key.
32-
pub trait KeyTrait: PartialEq + Eq + Send + Sync + Sized + Clone + Zeroize + ZeroizeOnDrop {
33-
/// Number of bytes in the serialized key.
34-
type Length: Eq + generic_array::ArrayLength<u8>;
31+
pub trait KeyTrait<const LENGTH: usize>:
32+
PartialEq + Eq + Send + Sync + Sized + Clone + Zeroize + ZeroizeOnDrop
33+
{
34+
/// Key length
35+
const LENGTH: usize = LENGTH;
3536

3637
/// Convert the given key into a vector of bytes.
3738
#[must_use]
38-
fn to_bytes(&self) -> generic_array::GenericArray<u8, Self::Length>;
39+
fn to_bytes(&self) -> [u8; LENGTH];
3940

4041
/// Convert the given bytes into a key. An error is returned in case the
4142
/// conversion fails.

src/symmetric_crypto/aes_256_gcm_pure/dem.rs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,31 @@
22
33
use crate::{
44
symmetric_crypto::{
5-
aes_256_gcm_pure::Aes256GcmCrypto, nonce::NonceTrait, Dem, SymmetricCrypto,
5+
aes_256_gcm_pure::{Aes256GcmCrypto, KEY_LENGTH},
6+
nonce::NonceTrait,
7+
Dem, SymmetricCrypto,
68
},
7-
CryptoCoreError, KeyTrait,
9+
CryptoCoreError,
810
};
9-
use generic_array::typenum::Unsigned;
1011
use rand_core::{CryptoRng, RngCore};
1112
use std::convert::TryFrom;
1213

13-
impl Dem for Aes256GcmCrypto {
14+
impl Dem<KEY_LENGTH> for Aes256GcmCrypto {
1415
fn encaps<R: RngCore + CryptoRng>(
1516
rng: &mut R,
1617
secret_key: &[u8],
1718
additional_data: Option<&[u8]>,
1819
message: &[u8],
1920
) -> Result<Vec<u8>, CryptoCoreError> {
20-
let key_length = <<Self::Key as KeyTrait>::Length as Unsigned>::to_usize();
21-
if secret_key.len() < key_length {
21+
if secret_key.len() < KEY_LENGTH {
2222
return Err(CryptoCoreError::SizeError {
2323
given: secret_key.len(),
24-
expected: key_length,
24+
expected: KEY_LENGTH,
2525
});
2626
}
2727
// AES GCM includes an authentication method
2828
// there is no need for parsing a MAC key
29-
let key = Self::Key::try_from(&secret_key[..key_length])?;
29+
let key = Self::Key::try_from(&secret_key[..KEY_LENGTH])?;
3030
let nonce = Self::Nonce::new(rng);
3131
let mut c = Self::encrypt(&key, message, &nonce, additional_data)
3232
.map_err(|err| CryptoCoreError::EncryptionError(err.to_string()))?;
@@ -42,16 +42,15 @@ impl Dem for Aes256GcmCrypto {
4242
additional_data: Option<&[u8]>,
4343
encapsulation: &[u8],
4444
) -> Result<Vec<u8>, CryptoCoreError> {
45-
let key_length = <<Self::Key as KeyTrait>::Length as Unsigned>::to_usize();
46-
if secret_key.len() < key_length {
45+
if secret_key.len() < KEY_LENGTH {
4746
return Err(CryptoCoreError::SizeError {
4847
given: secret_key.len(),
49-
expected: key_length,
48+
expected: KEY_LENGTH,
5049
});
5150
}
5251
// AES GCM includes an authentication method
5352
// there is no need for parsing a MAC key
54-
let key = Self::Key::try_from(&secret_key[..key_length])?;
53+
let key = Self::Key::try_from(&secret_key[..KEY_LENGTH])?;
5554
let nonce = Self::Nonce::try_from(&encapsulation[..Self::Nonce::LENGTH])?;
5655
Self::decrypt(
5756
&key,
@@ -71,14 +70,13 @@ mod tests {
7170
symmetric_crypto::{aes_256_gcm_pure::Aes256GcmCrypto, Dem},
7271
CryptoCoreError,
7372
};
74-
use generic_array::typenum::U256;
7573

7674
#[test]
7775
fn test_dem() -> Result<(), CryptoCoreError> {
7876
let m = b"my secret message";
7977
let additional_data = Some(b"public tag".as_slice());
8078
let mut rng = CsRng::new();
81-
let secret_key = rng.generate_random_bytes::<U256>();
79+
let secret_key = rng.generate_random_bytes::<256>();
8280
let c = Aes256GcmCrypto::encaps(&mut rng, &secret_key, additional_data, m)?;
8381
let res = Aes256GcmCrypto::decaps(&secret_key, additional_data, &c)?;
8482
if res != m {

0 commit comments

Comments
 (0)