forked from exonum/exonum
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test noise-handshake with converted keys (exonum#722) [ECR-1483]
- Loading branch information
1 parent
60f497d
commit a14d3be
Showing
8 changed files
with
209 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ deserializer | |
deserializes | ||
deserializing | ||
DESTDIR | ||
diffie | ||
doctests | ||
emsp | ||
Exonum | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// Copyright 2018 The Exonum Team | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
//! X25519 related types and methods used in Diffie-Hellman key exchange. | ||
use sodiumoxide::crypto::sign::ed25519::{convert_ed_keypair_to_curve25519, | ||
PublicKey as PublicKeySodium, | ||
SecretKey as SecretKeySodium}; | ||
|
||
use std::fmt; | ||
|
||
use crypto::{self, PUBLIC_KEY_LENGTH}; | ||
|
||
const SECRET_KEY_LENGTH: usize = 32; | ||
const BYTES_IN_DEBUG: usize = 4; | ||
|
||
/// Converts Ed25519 keys to Curve25519. | ||
/// | ||
/// Ed25519 keys used for signatures can be converted to Curve25519 and used for | ||
/// Diffie-Hellman key exchange. | ||
/// | ||
/// # Examples | ||
/// | ||
/// The example below generates a pair of secret and public Ed25519 keys and | ||
/// converts it to pair of Curve25519 keys. | ||
/// | ||
/// ``` | ||
/// use exonum::crypto; | ||
/// # crypto::init(); | ||
/// | ||
/// let (pk, sk) = crypto::gen_keypair(); | ||
/// let (public_key, secret_key) = crypto::x25519::into_x25519_keypair(pk, sk).unwrap(); | ||
/// ``` | ||
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] | ||
pub fn into_x25519_keypair( | ||
pk: crypto::PublicKey, | ||
sk: crypto::SecretKey, | ||
) -> Option<(PublicKey, SecretKey)> { | ||
let pk_sod = PublicKeySodium::from_slice(&pk[..])?; | ||
let sk_sod = SecretKeySodium::from_slice(&sk[..])?; | ||
|
||
let (pk, sk) = convert_ed_keypair_to_curve25519(pk_sod, sk_sod); | ||
|
||
let mut secret_key = [0; SECRET_KEY_LENGTH]; | ||
secret_key.clone_from_slice(&sk.0[..SECRET_KEY_LENGTH]); | ||
|
||
Some((PublicKey(pk.0), SecretKey(secret_key))) | ||
} | ||
|
||
macro_rules! implement_x25519_type { | ||
($(#[$attr:meta])* struct $name:ident, $size:expr) => ( | ||
#[derive(Clone, Copy)] | ||
$(#[$attr])* | ||
pub struct $name([u8; $size]); | ||
|
||
impl AsRef<[u8]> for $name { | ||
fn as_ref(&self) -> &[u8] { | ||
self.0.as_ref() | ||
} | ||
} | ||
|
||
impl fmt::Debug for $name { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, stringify!($name))?; | ||
write!(f, "(")?; | ||
for i in &self.as_ref()[0..BYTES_IN_DEBUG] { | ||
write!(f, "{:02X}", i)? | ||
} | ||
write!(f, ")") | ||
} | ||
} | ||
) | ||
} | ||
|
||
implement_x25519_type! { | ||
/// Curve25519 public key used in key exchange. | ||
/// This key cannot be directly generated and can only be converted | ||
/// from Ed25519 `PublicKey`. | ||
/// | ||
/// See: [`into_x25519_keypair()`][1] | ||
/// | ||
/// [1]: fn.into_x25519_keypair.html | ||
struct PublicKey, PUBLIC_KEY_LENGTH | ||
} | ||
|
||
implement_x25519_type! { | ||
/// Curve25519 secret key used in key exchange. | ||
/// This key cannot be directly generated and can only be converted | ||
/// from Ed25519 `SecretKey`. | ||
/// | ||
/// See: [`into_x25519_keypair()`][1] | ||
/// | ||
/// [1]: fn.into_x25519_keypair.html | ||
struct SecretKey, SECRET_KEY_LENGTH | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Copyright 2018 The Exonum Team | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
use snow::types::Dh; | ||
use snow::wrappers::crypto_wrapper::Dh25519; | ||
use snow::NoiseBuilder; | ||
|
||
use crypto::PUBLIC_KEY_LENGTH; | ||
use crypto::{gen_keypair, x25519::into_x25519_keypair}; | ||
|
||
#[test] | ||
fn test_convert_ed_to_curve_dh() { | ||
// Generate Ed25519 keys for initiator and responder. | ||
let (public_key_i, secret_key_i) = gen_keypair(); | ||
let (public_key_r, secret_key_r) = gen_keypair(); | ||
|
||
// Convert to Curve25519 keys. | ||
let (public_key_i, secret_key_i) = into_x25519_keypair(public_key_i, secret_key_i).unwrap(); | ||
let (public_key_r, secret_key_r) = into_x25519_keypair(public_key_r, secret_key_r).unwrap(); | ||
|
||
// Do DH. | ||
let mut keypair_i: Dh25519 = Default::default(); | ||
keypair_i.set(secret_key_i.as_ref()); | ||
let mut output_i = [0u8; PUBLIC_KEY_LENGTH]; | ||
keypair_i.dh(public_key_r.as_ref(), &mut output_i); | ||
|
||
let mut keypair_r: Dh25519 = Default::default(); | ||
keypair_r.set(secret_key_r.as_ref()); | ||
let mut output_r = [0u8; PUBLIC_KEY_LENGTH]; | ||
keypair_r.dh(public_key_i.as_ref(), &mut output_r); | ||
|
||
assert_eq!(output_i, output_r); | ||
} | ||
|
||
#[test] | ||
fn test_converted_keys_handshake() { | ||
const MSG_SIZE: usize = 4096; | ||
static PATTERN: &'static str = "Noise_XK_25519_ChaChaPoly_SHA256"; | ||
|
||
// Handshake initiator keypair. | ||
let (public_key_i, secret_key_i) = gen_keypair(); | ||
// Handshake responder keypair. | ||
let (public_key_r, secret_key_r) = gen_keypair(); | ||
|
||
// Convert to Curve25519 keys. | ||
let (_, secret_key_i) = into_x25519_keypair(public_key_i, secret_key_i).unwrap(); | ||
let (public_key_r, secret_key_r) = into_x25519_keypair(public_key_r, secret_key_r).unwrap(); | ||
|
||
let mut h_i = NoiseBuilder::new(PATTERN.parse().unwrap()) | ||
.local_private_key(secret_key_i.as_ref()) | ||
.remote_public_key(public_key_r.as_ref()) | ||
.build_initiator() | ||
.expect("Unable to create initiator"); | ||
|
||
let mut h_r = NoiseBuilder::new(PATTERN.parse().unwrap()) | ||
.local_private_key(secret_key_r.as_ref()) | ||
.build_responder() | ||
.expect("Unable to create responder"); | ||
|
||
let mut buffer_msg = [0u8; MSG_SIZE * 2]; | ||
let mut buffer_out = [0u8; MSG_SIZE * 2]; | ||
|
||
let len = h_i.write_message(&[0u8; 0], &mut buffer_msg).unwrap(); | ||
h_r.read_message(&buffer_msg[..len], &mut buffer_out) | ||
.unwrap(); | ||
let len = h_r.write_message(&[0u8; 0], &mut buffer_msg).unwrap(); | ||
h_i.read_message(&buffer_msg[..len], &mut buffer_out) | ||
.unwrap(); | ||
let len = h_i.write_message(&[0u8; 0], &mut buffer_msg).unwrap(); | ||
h_r.read_message(&buffer_msg[..len], &mut buffer_out) | ||
.unwrap(); | ||
|
||
h_r.into_transport_mode() | ||
.expect("Unable to transition session into transport mode"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters