summaryrefslogtreecommitdiff
path: root/webhook/src
diff options
context:
space:
mode:
authorMatthieu <matthieu@developershouse.xyz>2021-10-18 13:52:21 +0400
committerMatthieu <matthieu@developershouse.xyz>2021-10-18 13:52:21 +0400
commit2c39f7a6a1c3113337bc4e56b6e3cfa92f703fb3 (patch)
tree01ceccb670f171c7bd12a5c0969c74572c5457e7 /webhook/src
parent9023aa354902844b7d6100f55c3064afedd88966 (diff)
parentd55a128729ca94e727ce3a1ab4fb6af08d3cd109 (diff)
fix merge conflicts
Diffstat (limited to 'webhook/src')
-rw-r--r--webhook/src/handler/handler.rs4
-rw-r--r--webhook/src/handler/make_service.rs3
-rw-r--r--webhook/src/handler/signature.rs39
-rw-r--r--webhook/src/handler/tests/handler_integration.rs15
-rw-r--r--webhook/src/handler/tests/signature.rs17
-rw-r--r--webhook/src/handler/tests/utils.rs49
-rw-r--r--webhook/src/main.rs4
7 files changed, 51 insertions, 80 deletions
diff --git a/webhook/src/handler/handler.rs b/webhook/src/handler/handler.rs
index 74a1762..a07f995 100644
--- a/webhook/src/handler/handler.rs
+++ b/webhook/src/handler/handler.rs
@@ -19,12 +19,14 @@ use std::{
task::{Context, Poll},
time::Duration,
};
+use ed25519_dalek::PublicKey;
/// Hyper service used to handle the discord webhooks
#[derive(Clone)]
pub struct HandlerService {
pub config: Arc<Config>,
pub nats: Arc<Connection>,
+ pub public_key: Arc<PublicKey>
}
impl HandlerService {
@@ -38,7 +40,7 @@ impl HandlerService {
let contatenated_data = [timestamp.as_bytes().to_vec(), data.to_vec()].concat();
if let Ok(signature_str) = &signature.to_str() {
if validate_signature(
- &self.config.discord.public_key,
+ &self.public_key,
&contatenated_data,
signature_str,
) {
diff --git a/webhook/src/handler/make_service.rs b/webhook/src/handler/make_service.rs
index deeb2fe..9e90436 100644
--- a/webhook/src/handler/make_service.rs
+++ b/webhook/src/handler/make_service.rs
@@ -7,10 +7,12 @@ use std::{
sync::Arc,
task::{Context, Poll},
};
+use ed25519_dalek::PublicKey;
pub struct MakeSvc {
pub settings: Arc<Config>,
pub nats: Arc<Connection>,
+ pub public_key: Arc<PublicKey>
}
impl<T> Service<T> for MakeSvc {
@@ -26,6 +28,7 @@ impl<T> Service<T> for MakeSvc {
ready(Ok(HandlerService {
config: self.settings.clone(),
nats: self.nats.clone(),
+ public_key: self.public_key.clone()
}))
}
}
diff --git a/webhook/src/handler/signature.rs b/webhook/src/handler/signature.rs
index e4c7d53..748fa6a 100644
--- a/webhook/src/handler/signature.rs
+++ b/webhook/src/handler/signature.rs
@@ -1,5 +1,8 @@
use common::prometheus::{Counter, HistogramVec, labels, opts, register_counter, register_histogram_vec};
-use libsodium_sys::crypto_sign_ed25519_verify_detached;
+use ed25519_dalek::PublicKey;
+use ed25519_dalek::Verifier;
+use ed25519_dalek::Signature;
+use std::convert::TryInto;
lazy_static::lazy_static! {
static ref SIGNATURE_TIME_HISTOGRAM: HistogramVec = register_histogram_vec!(
@@ -15,36 +18,22 @@ lazy_static::lazy_static! {
)).unwrap();
}
-/// Checks the signature of a given data using the hex signature and the public key.
-pub fn validate_signature(hex_public_key: &str, data: &Vec<u8>, hex_signature: &str) -> bool {
+fn demo<T, const N: usize>(v: Vec<T>) -> [T; N] {
+ v.try_into()
+ .unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len()))
+}
+
+pub fn validate_signature(public_key: &PublicKey, data: &Vec<u8>, hex_signature: &str) -> bool {
SIGNATURE_COUNTER.inc();
let timer = SIGNATURE_TIME_HISTOGRAM.with_label_values(&["webhook_main"]).start_timer();
- // First, we need to check if the signature & private key is valid base64.
let signature_result = hex::decode(hex_signature);
- let public_key_result = hex::decode(hex_public_key);
let mut result = false;
- if signature_result.is_ok() && public_key_result.is_ok() {
- // Since we now have the signatures in u8 vectors. We will initialize all the
- // parameters for the ffi call to sodium.
- let signature_pointer = signature_result.unwrap();
- let private_key_pointer = public_key_result.unwrap();
-
- let data_pointer = data.as_ptr();
- let data_len = data.len() as u64;
-
- // A ffi call is considered unsafe by the Rust compiler
- // we assume all the parameters are correct for the call
- unsafe {
- // If the signature is valid, sodium will return 0
- result = crypto_sign_ed25519_verify_detached(
- signature_pointer.as_ptr(),
- data_pointer,
- data_len,
- private_key_pointer.as_ptr(),
- ) == 0;
- }
+ if let Ok(signature) = signature_result {
+ let sig = Signature::from(demo(signature));
+
+ result = public_key.verify(data, &sig).is_ok();
}
timer.observe_duration();
diff --git a/webhook/src/handler/tests/handler_integration.rs b/webhook/src/handler/tests/handler_integration.rs
index 6031428..906b347 100644
--- a/webhook/src/handler/tests/handler_integration.rs
+++ b/webhook/src/handler/tests/handler_integration.rs
@@ -4,6 +4,7 @@ use ctor;
use hyper::{Body, Method, Request, StatusCode};
use lazy_static::lazy_static;
use serde_json::json;
+use ed25519_dalek::Keypair;
use common::{
config::test_init,
@@ -35,7 +36,7 @@ static mut NATS: Option<Container<Cli, GenericImage>> = None;
static mut SETTINGS: Option<Settings<Config>> = None;
lazy_static! {
- static ref KEYPAIR: (String, [u8; 64]) = generate_keypair();
+ static ref TEST_KEYPAIR: Keypair = generate_keypair();
static ref DOCKER: Cli = Cli::default();
}
@@ -59,7 +60,7 @@ unsafe fn init() {
address: "0.0.0.0".to_string(),
},
discord: crate::config::Discord {
- public_key: KEYPAIR.0.clone(),
+ public_key: hex::encode(TEST_KEYPAIR.public.clone()),
client_id: 0,
},
},
@@ -103,7 +104,7 @@ async fn respond_to_pings() {
let ping = json!({ "type": 1, "id": "0", "application_id": "0", "token": "random token", "version": 1 }).to_string();
let timestamp = "my datetime :)";
let signature_data = [timestamp.as_bytes().to_vec(), ping.as_bytes().to_vec()].concat();
- let signature = sign_message(signature_data, KEYPAIR.1);
+ let signature = sign_message(signature_data, &TEST_KEYPAIR);
let req = Request::builder()
.method(Method::POST)
@@ -140,7 +141,7 @@ async fn response_500_when_no_nats_response() {
let ping = json!({ "type": 2, "id": "0", "application_id": "0", "token": "random token", "version": 1 }).to_string();
let timestamp = "my datetime :)";
let signature_data = [timestamp.as_bytes().to_vec(), ping.as_bytes().to_vec()].concat();
- let signature = sign_message(signature_data, KEYPAIR.1);
+ let signature = sign_message(signature_data, &TEST_KEYPAIR);
// we must timeout
let req = Request::builder()
@@ -166,7 +167,7 @@ async fn respond_from_nats_response() {
let ping = json!({ "type": 2, "id": "0", "application_id": "0", "token": "random token", "version": 1 }).to_string();
let timestamp = "my datetime :)";
let signature_data = [timestamp.as_bytes().to_vec(), ping.as_bytes().to_vec()].concat();
- let signature = sign_message(signature_data, KEYPAIR.1);
+ let signature = sign_message(signature_data, &TEST_KEYPAIR);
sub.with_handler(move |msg| {
info!("Received {}", &msg);
@@ -191,7 +192,7 @@ async fn response_400_when_invalid_json_body() {
let ping = "{".to_string();
let timestamp = "my datetime :)";
let signature_data = [timestamp.as_bytes().to_vec(), ping.as_bytes().to_vec()].concat();
- let signature = sign_message(signature_data, KEYPAIR.1);
+ let signature = sign_message(signature_data, &TEST_KEYPAIR);
let req = Request::builder()
.method(Method::POST)
@@ -212,7 +213,7 @@ async fn response_400_when_invalid_utf8_body() {
let timestamp = "my datetime :)";
let signature_data = [timestamp.as_bytes().to_vec(), ping.to_vec()].concat();
- let signature = sign_message(signature_data, KEYPAIR.1);
+ let signature = sign_message(signature_data, &TEST_KEYPAIR);
let req = Request::builder()
.method(Method::POST)
diff --git a/webhook/src/handler/tests/signature.rs b/webhook/src/handler/tests/signature.rs
index 475e446..490143b 100644
--- a/webhook/src/handler/tests/signature.rs
+++ b/webhook/src/handler/tests/signature.rs
@@ -1,30 +1,33 @@
use crate::handler::signature::validate_signature;
-
+use ed25519_dalek::PublicKey;
#[test]
fn validate_signature_test() {
let signature = "543ec3547d57f9ddb1ec4c5c36503ebf288ffda3da3d510764c9a49c2abb57690ef974c63d174771bdd2481de1066966f57abbec12a3ec171b9f6e2373837002";
- let public_key = "eefe0c24473737cb2035232e3b4eb91c206f0a14684168f3503f7d8316058d6f";
let content = "message de test incroyable".as_bytes().to_vec();
- assert!(validate_signature(public_key, &content, signature))
+ let public_key = PublicKey::from_bytes(&hex::decode("eefe0c24473737cb2035232e3b4eb91c206f0a14684168f3503f7d8316058d6f").unwrap()).unwrap();
+
+ assert!(validate_signature(&public_key, &content, signature))
}
#[test]
fn validate_signature_reverse_test() {
let signature = "543ec3547d57f9ddb1ec4c5c36503ebf288ffda3da3d510764c9a49c2abb57690ef974c63d174771bdd2481de1066966f57abbec12a3ec171b9f6e2373837002";
- let public_key = "c029eea18437292c87c62aec34e7d1bd4e38fe6126f3f7c446de6375dc666044";
+ let public_key = PublicKey::from_bytes(&hex::decode("c029eea18437292c87c62aec34e7d1bd4e38fe6126f3f7c446de6375dc666044").unwrap()).unwrap();
+
let content = "ceci est un test qui ne fonctionnera pas!"
.as_bytes()
.to_vec();
- assert!(!validate_signature(public_key, &content, signature))
+ assert!(!validate_signature(&public_key, &content, signature))
}
#[test]
fn invalid_hex() {
let signature = "zzz";
- let public_key = "zzz";
+ let public_key = PublicKey::from_bytes(&hex::decode("c029eea18437292c87c62aec34e7d1bd4e38fe6126f3f7c446de6375dc666044").unwrap()).unwrap();
+
let content = "ceci est un test qui ne fonctionnera pas!"
.as_bytes()
.to_vec();
- assert!(!validate_signature(public_key, &content, signature))
+ assert!(!validate_signature(&public_key, &content, signature))
} \ No newline at end of file
diff --git a/webhook/src/handler/tests/utils.rs b/webhook/src/handler/tests/utils.rs
index f8cdac2..5e59f09 100644
--- a/webhook/src/handler/tests/utils.rs
+++ b/webhook/src/handler/tests/utils.rs
@@ -1,46 +1,15 @@
-pub fn generate_keypair() -> (
- String,
- [u8; libsodium_sys::crypto_sign_ed25519_SECRETKEYBYTES as usize],
-) {
- use libsodium_sys::crypto_sign_ed25519_keypair;
- let pk_s: String;
+use rand::rngs::OsRng;
+use ed25519_dalek::{Signer, Keypair, Signature};
- let mut pk = [0; libsodium_sys::crypto_sign_ed25519_PUBLICKEYBYTES as usize];
- let mut sk = [0; libsodium_sys::crypto_sign_ed25519_SECRETKEYBYTES as usize];
-
- let pk_p = pk.as_mut_ptr();
- let sk_p = sk.as_mut_ptr();
-
- // generate keypair
- unsafe {
- if crypto_sign_ed25519_keypair(pk_p, sk_p) < 0 {
- panic!("keypair generation failed!");
- }
- };
-
- pk_s = hex::encode(pk);
- return (pk_s, sk);
+pub fn generate_keypair() -> Keypair {
+ let mut csprng = OsRng{};
+ Keypair::generate(&mut csprng)
}
pub fn sign_message(
- msg: Vec<u8>,
- sk: [u8; libsodium_sys::crypto_sign_ed25519_SECRETKEYBYTES as usize],
+ message: Vec<u8>,
+ keypair: &Keypair,
) -> String {
- use libc::c_ulonglong;
- use libsodium_sys::crypto_sign_ed25519_detached;
-
- let len = msg.len();
- let mut signature_len: c_ulonglong = 0;
- let mut str = [0; 64];
- unsafe {
- crypto_sign_ed25519_detached(
- str.as_mut_ptr(),
- &mut signature_len,
- msg.as_ptr(),
- len as u64,
- sk.as_ptr(),
- );
- };
-
- return hex::encode(str);
+ let signature: Signature = keypair.sign(&message);
+ return hex::encode(signature.to_bytes());
} \ No newline at end of file
diff --git a/webhook/src/main.rs b/webhook/src/main.rs
index 98e5f13..00d42ee 100644
--- a/webhook/src/main.rs
+++ b/webhook/src/main.rs
@@ -6,6 +6,7 @@ use crate::handler::make_service::MakeSvc;
use crate::config::Config;
use common::config::Settings;
use common::log::{error, info};
+use ed25519_dalek::PublicKey;
use hyper::Server;
#[tokio::main]
@@ -30,9 +31,12 @@ async fn start(settings: Settings<Config>) {
);
let config = Arc::new(settings.config);
+ let public_key =
+ Arc::new(PublicKey::from_bytes(&hex::decode(&config.discord.public_key).unwrap()).unwrap());
let server = Server::bind(&addr).serve(MakeSvc {
settings: config,
nats: Arc::new(settings.nats.into()),
+ public_key: public_key,
});
if let Err(e) = server.await {