Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate gateway registry with nym-wireguard #4010

Merged
merged 7 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ license = "Apache-2.0"
anyhow = "1.0.71"
async-trait = "0.1.68"
bip39 = { version = "2.0.0", features = ["zeroize"] }
boringtun = { git = "https://github.com/cloudflare/boringtun", rev = "e1d6360d6ab4529fc942a078e4c54df107abe2ba" }
cfg-if = "1.0.0"
cosmwasm-derive = "=1.3.0"
cosmwasm-schema = "=1.3.0"
Expand Down
2 changes: 1 addition & 1 deletion common/commands/src/validator/cosmwasm/init_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub async fn init(args: Args, client: SigningClient, network_details: &NymNetwor
// by default we make ourselves an admin, let me know if you don't like that behaviour
let opts = Some(InstantiateOptions {
funds,
admin: Some(args.admin.unwrap_or_else(|| client.address().clone())),
admin: Some(args.admin.unwrap_or_else(|| client.address())),
});

let msg: serde_json::Value =
Expand Down
15 changes: 11 additions & 4 deletions common/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@ edition = "2021"
rust-version = "1.58"

[dependencies]
base64 = "0.21.4"
boringtun = { workspace = true, optional = true }
dashmap = "5.5.3"
eyre = "0.6.5"
hmac = "0.12.1"
itertools = "0.11"
log = { workspace = true }
itertools = "0.10"
reqwest = { workspace = true }
schemars = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = { workspace = true }
strum = { version = "0.23", features = ["derive"] }
sha2 = "0.10.8"
strum = { version = "0.25", features = ["derive"] }
thiserror = { workspace = true }
url = { workspace = true }
ts-rs = { workspace = true }
url = { workspace = true }
x25519-dalek = { version = "2.0.0", features = ["static_secrets"] }

cosmwasm-std = { workspace = true }
cosmrs = { workspace = true }
Expand All @@ -27,11 +33,12 @@ nym-mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mix
nym-vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" }
nym-config = { path = "../../common/config" }
nym-coconut-interface = { path = "../../common/coconut-interface" }

nym-crypto = { path = "../../common/crypto", features = ["asymmetric"] }

[dev-dependencies]
tempfile = "3.3.0"

[features]
default = []
generate-ts = ["nym-mixnet-contract-common/generate-ts"]
wireguard = ["boringtun"]
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
use std::{
fmt,
hash::{Hash, Hasher},
net::SocketAddr,
ops::Deref,
str::FromStr,
};
use std::{net::SocketAddr, ops::Deref, str::FromStr};

use crate::wireguard::PeerPublicKey;
use base64::{engine::general_purpose, Engine};
use dashmap::DashMap;
use hmac::{Hmac, Mac};
Expand All @@ -14,45 +9,47 @@ use serde::{Deserialize, Serialize};
use sha2::Sha256;
use x25519_dalek::StaticSecret;

use crate::error::GatewayError;

#[derive(Debug, Clone, Deserialize, Serialize)]
pub(crate) enum ClientMessage {
pub enum ClientMessage {
Init(InitMessage),
Final(Client),
Final(GatewayClient),
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub(crate) struct InitMessage {
pub_key: ClientPublicKey,
pub struct InitMessage {
pub_key: PeerPublicKey,
}

impl InitMessage {
pub fn pub_key(&self) -> &ClientPublicKey {
pub fn pub_key(&self) -> &PeerPublicKey {
&self.pub_key
}
#[allow(dead_code)]
pub fn new(pub_key: ClientPublicKey) -> Self {
pub fn new(pub_key: PeerPublicKey) -> Self {
InitMessage { pub_key }
}
}

// Client that wants to register sends its PublicKey and SocketAddr bytes mac digest encrypted with a DH shared secret.
// Gateway can then verify pub_key payload using the sme process
#[derive(Debug, Clone, Deserialize, Serialize)]
pub(crate) struct Client {
pub struct GatewayClient {
// base64 encoded public key, using x25519-dalek for impl
pub(crate) pub_key: ClientPublicKey,
pub(crate) socket: SocketAddr,
pub(crate) mac: ClientMac,
pub pub_key: PeerPublicKey,
pub socket: SocketAddr,
pub mac: ClientMac,
}

pub type HmacSha256 = Hmac<Sha256>;

impl Client {
impl GatewayClient {
// Reusable secret should be gateways Wireguard PK
// Client should perform this step when generating its payload, using its own WG PK
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), GatewayError> {
pub fn verify(
&self,
gateway_key: &PrivateKey,
nonce: u64,
) -> Result<(), Box<dyn std::error::Error>> {
#[allow(clippy::expect_used)]
let static_secret =
StaticSecret::try_from(gateway_key.to_bytes()).expect("This is infalliable");
Expand All @@ -65,7 +62,7 @@ impl Client {
Ok(mac.verify_slice(&self.mac)?)
}

pub fn pub_key(&self) -> &ClientPublicKey {
pub fn pub_key(&self) -> &PeerPublicKey {
&self.pub_key
}

Expand All @@ -74,11 +71,8 @@ impl Client {
}
}

// This should go into nym-wireguard crate
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ClientPublicKey(x25519_dalek::PublicKey);
#[derive(Debug, Clone)]
pub(crate) struct ClientMac(Vec<u8>);
pub struct ClientMac(Vec<u8>);

impl ClientMac {
#[allow(dead_code)]
Expand All @@ -95,18 +89,6 @@ impl Deref for ClientMac {
}
}

impl fmt::Display for ClientPublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", general_purpose::STANDARD.encode(self.0.as_bytes()))
}
}

impl Hash for ClientPublicKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.as_bytes().hash(state)
}
}

impl FromStr for ClientMac {
type Err = String;

Expand All @@ -132,50 +114,4 @@ impl<'de> Deserialize<'de> for ClientMac {
}
}

impl ClientPublicKey {
#[allow(dead_code)]
pub fn new(key: x25519_dalek::PublicKey) -> Self {
ClientPublicKey(key)
}

pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}

impl Deref for ClientPublicKey {
type Target = x25519_dalek::PublicKey;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl FromStr for ClientPublicKey {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let key_bytes: [u8; 32] = general_purpose::STANDARD
.decode(s)
.map_err(|_| "Could not base64 decode public key representation".to_string())?
.try_into()
.map_err(|_| "Invalid key length".to_string())?;
Ok(ClientPublicKey(x25519_dalek::PublicKey::from(key_bytes)))
}
}

impl Serialize for ClientPublicKey {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let encoded_key = general_purpose::STANDARD.encode(self.0.as_bytes());
serializer.serialize_str(&encoded_key)
}
}

impl<'de> Deserialize<'de> for ClientPublicKey {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let encoded_key = String::deserialize(deserializer)?;
Ok(ClientPublicKey::from_str(&encoded_key).map_err(serde::de::Error::custom))?
}
}

pub(crate) type ClientRegistry = DashMap<SocketAddr, Client>;
pub type GatewayClientRegistry = DashMap<PeerPublicKey, GatewayClient>;
4 changes: 4 additions & 0 deletions common/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ pub mod error;
pub mod fees;
pub mod gas;
pub mod gateway;
#[cfg(feature = "wireguard")]
pub mod gateway_client_registration;
pub mod helpers;
pub mod mixnode;
pub mod pending_events;
pub mod transaction;
pub mod vesting;
#[cfg(feature = "wireguard")]
pub mod wireguard;
durch marked this conversation as resolved.
Show resolved Hide resolved
71 changes: 71 additions & 0 deletions common/types/src/wireguard.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::{
fmt,
hash::{Hash, Hasher},
ops::Deref,
str::FromStr,
};

use base64::{engine::general_purpose, Engine};
use boringtun::x25519::PublicKey;
use serde::Serialize;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PeerPublicKey(PublicKey);

impl fmt::Display for PeerPublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", general_purpose::STANDARD.encode(self.0.as_bytes()))
}
}

impl Hash for PeerPublicKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.as_bytes().hash(state)
}
}

impl PeerPublicKey {
#[allow(dead_code)]
pub fn new(key: PublicKey) -> Self {
PeerPublicKey(key)
}

pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}

impl Deref for PeerPublicKey {
type Target = PublicKey;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl FromStr for PeerPublicKey {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let key_bytes: [u8; 32] = general_purpose::STANDARD
.decode(s)
.map_err(|_| "Could not base64 decode public key representation".to_string())?
.try_into()
.map_err(|_| "Invalid key length".to_string())?;
Ok(PeerPublicKey(PublicKey::from(key_bytes)))
}
}

impl Serialize for PeerPublicKey {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let encoded_key = general_purpose::STANDARD.encode(self.0.as_bytes());
serializer.serialize_str(&encoded_key)
}
}

impl<'de> serde::Deserialize<'de> for PeerPublicKey {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let encoded_key = String::deserialize(deserializer)?;
Ok(PeerPublicKey::from_str(&encoded_key).map_err(serde::de::Error::custom))?
}
}
Loading
Loading