Make secio almost compile for asmjs/wasm (#519)

* Use the sha2 crate in the handshake

* Return a Digest in algo_support instead of a ring ref

* Switch to ed25519-dalek for keys

* Make ring more or less optional

* Switch to ed25519_dalek for the verification

* Extract the key exchange to its own module

* Remove the ring RNG from the handshake

* Some warning fixes and forgot file

* Move key exchange to own module

* Remove usage of ring::digest

* Remove ring from handshake entirely

* Implement ECDH for WebCrypto

* Remove the libp2p-secio feature

* Fix ring being included

* Address some concerns

* Provde some panics in WebCrypto

* Prove the Hmac panic

* Prove more panics
This commit is contained in:
Pierre Krieger
2018-10-01 15:42:40 +02:00
committed by GitHub
parent 7208bba92b
commit e3efc2dc9a
12 changed files with 570 additions and 214 deletions

View File

@ -0,0 +1,70 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//! Implementation of the key agreement process using the `ring` library.
use futures::{future, prelude::*};
use ring::agreement as ring_agreement;
use ring::rand as ring_rand;
use untrusted::Input as UntrustedInput;
use {KeyAgreement, SecioError};
impl Into<&'static ring_agreement::Algorithm> for KeyAgreement {
#[inline]
fn into(self) -> &'static ring_agreement::Algorithm {
match self {
KeyAgreement::EcdhP256 => &ring_agreement::ECDH_P256,
KeyAgreement::EcdhP384 => &ring_agreement::ECDH_P384,
}
}
}
/// Opaque private key type.
pub type AgreementPrivateKey = ring_agreement::EphemeralPrivateKey;
/// Generates a new key pair as part of the exchange.
///
/// Returns the opaque private key and the corresponding public key.
pub fn generate_agreement(algorithm: KeyAgreement) -> impl Future<Item = (AgreementPrivateKey, Vec<u8>), Error = SecioError> {
let rng = ring_rand::SystemRandom::new();
match ring_agreement::EphemeralPrivateKey::generate(algorithm.into(), &rng) {
Ok(tmp_priv_key) => {
let mut tmp_pub_key: Vec<u8> = (0 .. tmp_priv_key.public_key_len()).map(|_| 0).collect();
tmp_priv_key.compute_public_key(&mut tmp_pub_key).unwrap();
future::ok((tmp_priv_key, tmp_pub_key))
},
Err(_) => {
debug!("failed to generate ECDH key");
future::err(SecioError::EphemeralKeyGenerationFailed)
},
}
}
/// Finish the agreement. On success, returns the shared key that both remote agreed upon.
pub fn agree(algorithm: KeyAgreement, my_private_key: AgreementPrivateKey, other_public_key: &[u8], _out_size: usize)
-> impl Future<Item = Vec<u8>, Error = SecioError>
{
ring_agreement::agree_ephemeral(my_private_key, algorithm.into(),
UntrustedInput::from(other_public_key),
SecioError::SecretGenerationFailed,
|key_material| Ok(key_material.to_vec()))
.into_future()
}