Skip to content

Commit

Permalink
Update ed25519-dalek to 2.0.0 (from 1.0.1)
Browse files Browse the repository at this point in the history
- With the update to `2` `ed25519-dalek` not longer depends on
  `[email protected]`.
- Bump `rand` dependency to `0.8` (from `0.7`).
- `ed25519-dalek` now provide the feature `zeroize` that provide
  implementation around the crate `zeroize`. That improve the secrety of
  the private key slightly (and is free).
- `*::generate` where put behind the feature `rand_core`.
- `PublicKey` was renamed by `VerifyingKey`.
- `SigningKey`:
  - Previously named `Keypair`.
  - Implement `Clone`.
  - No longer provide `as_bytes`. it was remplaced by
    `to_bytes`.
  - Implement `TryFrom<&[u8]>`.
  - Implement `From<[u8; 32]>`.
- `Signature::from_bytes` no longer return an error (now it take
  reference to an `[u8; 32]` instead of `[u8]`).

[Changelog](https://github.com/dalek-cryptography/curve25519-dalek/blob/e6675c67ceadecc3e22b561296490f4b7de9ff39/ed25519-dalek/CHANGELOG.md)

> I can't provide the diff between `2.0.0` and `1.0.1` since the project
> as migrate to a different repository.
> C.F: dalek-cryptography/ed25519-dalek#245 (comment)
  • Loading branch information
FirelightFlagboy committed Nov 2, 2023
1 parent 80f3ef3 commit a4dd703
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 182 deletions.
207 changes: 81 additions & 126 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ data-encoding = { version = "2.4.0", default-features = false }
diesel = { version = "2.1.3", default-features = false }
digest = { version = "0.10.7", default-features = false }
dirs = { version = "5.0.1", default-features = false }
ed25519-dalek = { version = "1.0.1", default-features = false }
ed25519-dalek = { version = "2.0.0", default-features = false }
email-address-parser = { version = "2.0.0", default-features = false }
env_logger = { version = "0.10.0", default-features = false }
event-listener = { version = "2.5.3", default-features = false }
Expand Down Expand Up @@ -145,7 +145,6 @@ proc-macro2 = { version = "1.0.69", default-features = false }
pyo3 = { version = "0.19.2", default-features = false }
quote = { version = "1.0.33", default-features = false }
# Two versions of `rand` needed in `libparsec_crypto`
rand_07 = { package = "rand", version = "0.7", default-features = false }
rand_08 = { package = "rand", version = "0.8", default-features = false }
rand = { version = "0.8.5", default-features = false }
regex = { version = "1.10.2", default-features = false }
Expand Down
7 changes: 1 addition & 6 deletions libparsec/crates/crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use-sodiumoxide = [
# "dep:getrandom_01",
# "dep:getrandom_02",
# "dep:lazy_static",
# "dep:rand_07",
# "dep:rand_08",
# "dep:rsa",
# "dep:sha1",
Expand Down Expand Up @@ -108,7 +107,7 @@ argon2 = { workspace = true, features = ["alloc", "password-hash", "rand"] } #
blake2 = { workspace = true, features = ["std"] } # Optional rustcrypto dep
crypto_box = { workspace = true, features = ["std", "salsa20", "rand_core"] } # Optional rustcrypto dep
digest = { workspace = true, features = ["core-api"] } # Optional rustcrypto dep
ed25519-dalek = { workspace = true, features = ["std", "rand", "u64_backend"] } # Optional rustcrypto dep
ed25519-dalek = { workspace = true, features = ["std", "zeroize", "fast", "rand_core"] } # Optional rustcrypto dep
generic-array = { workspace = true, features = ["serde"] } # Optional rustcrypto dep
lazy_static = { workspace = true } # Optional rustcrypto dep
rsa = { workspace = true, features = ["std", "pem"] } # Optional rustcrypto dep
Expand All @@ -126,10 +125,6 @@ crypto_secretbox = { workspace = true, features = ["alloc", "getrandom", "salsa2
# configuring wasm-unknown-unknown web support (see [features] part).
getrandom_01 = { workspace = true } # Optional rustcrypto dep
getrandom_02 = { workspace = true } # Optional rustcrypto dep
# On top of that we need to have access to the two version of rand (0.7 and 0.8)
# to provide the randomness configuration to the crypto functions.
# rand 0.7 relies on rand_core~=0.5/getrandom~=0.1
rand_07 = { workspace = true, features = ["std"] } # Optional rustcrypto dep
# rand 0.8 relies on rand_core~=0.6/getrandom~=0.2
rand_08 = { workspace = true, features = ["std", "std_rng"] } # Optional rustcrypto dep

Expand Down
50 changes: 18 additions & 32 deletions libparsec/crates/crypto/src/rustcrypto/sign.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS

use ed25519_dalek::{Keypair, Signature, Signer, Verifier};
use ed25519_dalek::{Signature, Signer, Verifier};
use serde::{Deserialize, Serialize};
use serde_bytes::Bytes;

Expand All @@ -10,25 +10,15 @@ use crate::CryptoError;
* SigningKey
*/

#[derive(Deserialize)]
#[derive(Deserialize, Clone)]
#[serde(try_from = "&Bytes")]
pub struct SigningKey(Keypair);
pub struct SigningKey(ed25519_dalek::SigningKey);

crate::impl_key_debug!(SigningKey);

impl Clone for SigningKey {
fn clone(&self) -> Self {
Self(
Keypair::from_bytes(&self.0.to_bytes()).expect(
"The input bytes come from the cloned signing key, which is a valid key size",
),
)
}
}

impl PartialEq for SigningKey {
fn eq(&self, other: &Self) -> bool {
self.as_ref() == other.as_ref()
self.0.to_bytes() == other.0.to_bytes()
}
}

Expand All @@ -42,11 +32,13 @@ impl SigningKey {
pub const SIGNATURE_SIZE: usize = ed25519_dalek::SIGNATURE_LENGTH;

pub fn verify_key(&self) -> VerifyKey {
VerifyKey(self.0.public)
VerifyKey(self.0.verifying_key())
}

pub fn generate() -> Self {
Self(Keypair::generate(&mut rand_07::thread_rng()))
Self(ed25519_dalek::SigningKey::generate(
&mut rand_08::thread_rng(),
))
}

/// Sign the message and prefix it with the signature.
Expand All @@ -61,31 +53,25 @@ impl SigningKey {
pub fn sign_only_signature(&self, data: &[u8]) -> [u8; Self::SIGNATURE_SIZE] {
self.0.sign(data).to_bytes()
}
}

impl AsRef<[u8]> for SigningKey {
#[inline]
fn as_ref(&self) -> &[u8] {
self.0.secret.as_bytes()
pub fn to_bytes(&self) -> [u8; Self::SIZE] {
self.0.to_bytes()
}
}

impl TryFrom<&[u8]> for SigningKey {
type Error = CryptoError;
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
let sk = ed25519_dalek::SecretKey::from_bytes(data).map_err(|_| Self::Error::DataSize)?;
let pk = ed25519_dalek::PublicKey::from(&sk);
Ok(Self(Keypair {
secret: sk,
public: pk,
}))
ed25519_dalek::SigningKey::try_from(data)
.map(Self)
.map_err(|_| Self::Error::DataSize)
}
}

impl From<[u8; Self::SIZE]> for SigningKey {
fn from(key: [u8; Self::SIZE]) -> Self {
// TODO: zero copy
Self::try_from(key.as_ref()).expect("Cannot fail because the provided secret key is the expected size of `ed25519_dalek::SecretKey::from_bytes`")
Self(ed25519_dalek::SigningKey::from(key))
}
}

Expand All @@ -101,7 +87,7 @@ impl Serialize for SigningKey {
where
S: serde::Serializer,
{
serializer.serialize_bytes(self.as_ref())
serializer.serialize_bytes(&self.to_bytes())
}
}

Expand All @@ -111,7 +97,7 @@ impl Serialize for SigningKey {

#[derive(Clone, PartialEq, Eq, Deserialize)]
#[serde(try_from = "&Bytes")]
pub struct VerifyKey(ed25519_dalek::PublicKey);
pub struct VerifyKey(ed25519_dalek::VerifyingKey);

crate::impl_key_debug!(VerifyKey);

Expand Down Expand Up @@ -156,7 +142,7 @@ impl VerifyKey {
raw_signature: &[u8; SigningKey::SIGNATURE_SIZE],
message: &[u8],
) -> Result<(), CryptoError> {
let signature = Signature::from_bytes(raw_signature).map_err(|_| CryptoError::Signature)?;
let signature = Signature::from_bytes(raw_signature);
self.0
.verify(message, &signature)
.map_err(|_| CryptoError::SignatureVerification)?;
Expand All @@ -174,7 +160,7 @@ impl AsRef<[u8]> for VerifyKey {
impl TryFrom<&[u8]> for VerifyKey {
type Error = CryptoError;
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
ed25519_dalek::PublicKey::from_bytes(data)
ed25519_dalek::VerifyingKey::try_from(data)
.map(Self)
.map_err(|_| Self::Error::DataSize)
}
Expand Down
6 changes: 3 additions & 3 deletions libparsec/crates/crypto/src/sodiumoxide/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ impl PrivateKey {
}

pub fn generate_shared_secret_key(&self, peer_public_key: &PublicKey) -> SecretKey {
let scalar = Scalar(self.as_ref().try_into().unwrap());
let scalar = Scalar(self.to_bytes());
let group_element = GroupElement(peer_public_key.as_ref().try_into().unwrap());
let mult = scalarmult(&scalar, &group_element).unwrap();
// TODO: too many copies...
let x: [u8; 32] = mult.as_ref().try_into().unwrap();
SecretKey::from(x)
}

pub fn to_bytes(&self) -> [u8; SECRETKEYBYTES] {
pub fn to_bytes(&self) -> [u8; Self::SIZE] {
self.0 .0
}
}
Expand All @@ -64,7 +64,7 @@ impl Serialize for PrivateKey {
where
S: serde::Serializer,
{
serializer.serialize_bytes(self.as_ref())
serializer.serialize_bytes(&self.to_bytes())
}
}

Expand Down
16 changes: 7 additions & 9 deletions libparsec/crates/crypto/src/sodiumoxide/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ impl SigningKey {

self.0.sign(data).to_bytes()
}

pub fn to_bytes(&self) -> [u8; Self::SIZE] {
// SecretKey is composed of Seed then PublicKey, we export only seed here
<[u8; Self::SIZE]>::try_from(&self.0 .0[..Self::SIZE])
.expect("The internal array is > Self::SIZE")
}
}

impl TryFrom<&[u8]> for SigningKey {
Expand All @@ -61,14 +67,6 @@ impl From<[u8; Self::SIZE]> for SigningKey {
}
}

impl AsRef<[u8]> for SigningKey {
#[inline]
fn as_ref(&self) -> &[u8] {
// SecretKey is composed of Seed then PublicKey, we export only seed here
&self.0 .0[..Self::SIZE]
}
}

impl TryFrom<&Bytes> for SigningKey {
type Error = CryptoError;
fn try_from(data: &Bytes) -> Result<Self, Self::Error> {
Expand All @@ -81,7 +79,7 @@ impl Serialize for SigningKey {
where
S: serde::Serializer,
{
serializer.serialize_bytes(self.as_ref())
serializer.serialize_bytes(&self.to_bytes())
}
}

Expand Down
2 changes: 1 addition & 1 deletion libparsec/crates/testbed/src/template/crc_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ impl CrcHash for HashDigest {
impl CrcHash for SigningKey {
fn crc_hash(&self, hasher: &mut crc32fast::Hasher) {
hasher.update(b"SigningKey");
hasher.update(self.as_ref());
hasher.update(&self.to_bytes());
}
}

Expand Down
2 changes: 1 addition & 1 deletion libparsec/crates/testbed/src/template/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ impl CrcHash for TestbedEventNewDevice {
self.author.crc_hash(state);
self.device_id.crc_hash(state);
self.device_label.crc_hash(state);
self.signing_key.as_ref().crc_hash(state);
self.signing_key.crc_hash(state);
self.local_symkey.crc_hash(state);
self.local_password.crc_hash(state);
self.certificate_index.crc_hash(state);
Expand Down
4 changes: 2 additions & 2 deletions server/src/api_crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ impl SigningKey {
PyBytes::new(py, self.0.sign_only_signature(data).as_slice())
}

fn encode<'py>(&self, py: Python<'py>) -> &'py PyBytes {
PyBytes::new(py, self.0.as_ref())
fn encode(&self) -> [u8; libparsec_types::SigningKey::SIZE] {
self.0.to_bytes()
}
}

Expand Down

0 comments on commit a4dd703

Please sign in to comment.