Added symmetric and asymmetric publish

This commit is contained in:
Daniel Sanchez Quiros 2022-10-04 19:10:51 +02:00
parent 6a427280bb
commit 0f7a4ae22c
4 changed files with 255 additions and 3 deletions

107
Cargo.lock generated
View File

@ -2,6 +2,41 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aead"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8"
dependencies = [
"crypto-common",
"generic-array",
]
[[package]]
name = "aes"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfe0133578c0986e1fe3dfcd4af1cc5b2dd6c3dbf534d69916ce16a2701d40ba"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
]
[[package]]
name = "aes-gcm"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"ghash",
"subtle",
]
[[package]]
name = "aho-corasick"
version = "0.7.19"
@ -105,6 +140,16 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cipher"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
dependencies = [
"crypto-common",
"inout",
]
[[package]]
name = "clang-sys"
version = "1.4.0"
@ -184,6 +229,17 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"rand_core",
"typenum",
]
[[package]]
name = "crypto-mac"
version = "0.8.0"
@ -194,6 +250,15 @@ dependencies = [
"subtle",
]
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
"cipher",
]
[[package]]
name = "data-encoding"
version = "2.3.2"
@ -258,6 +323,16 @@ dependencies = [
"wasi",
]
[[package]]
name = "ghash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]]
name = "glob"
version = "0.3.0"
@ -332,6 +407,15 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array",
]
[[package]]
name = "itoa"
version = "1.0.3"
@ -518,6 +602,18 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "polyval"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
[[package]]
name = "ppv-lite86"
version = "0.2.16"
@ -843,6 +939,16 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "universal-hash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5"
dependencies = [
"crypto-common",
"subtle",
]
[[package]]
name = "unsigned-varint"
version = "0.7.1"
@ -870,6 +976,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
name = "waku"
version = "0.1.0"
dependencies = [
"aes-gcm",
"hex",
"libsecp256k1",
"multiaddr",

View File

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
aes-gcm = { version = "0.10", features = ["aes"] }
hex = "0.4"
libsecp256k1 = "0.7"
multiaddr = "0.14"

View File

@ -11,6 +11,7 @@ pub type ContentTopic = String;
pub type WakuMessageVersion = usize;
/// Base58 encoded peer id
pub type PeerId = String;
pub type MessageId = String;
/// JsonResponse wrapper.
/// `go-waku` ffi returns this type as a `char *` as per the [specification](https://rfc.vac.dev/spec/36/#jsonresponse-type)

View File

@ -1,6 +1,16 @@
use crate::general::{Encoding, WakuContentTopic, WakuPubSubTopic};
// std
use std::ffi::{CStr, CString};
use std::time::Duration;
// crates
use aes_gcm::{Aes256Gcm, Key};
use libsecp256k1::{PublicKey, SecretKey};
// internal
use crate::general::{
Encoding, JsonResponse, MessageId, Result, WakuContentTopic, WakuMessage, WakuPubSubTopic,
};
/// Create a content topic string according to [RFC 23](https://rfc.vac.dev/spec/23/)
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_content_topicchar-applicationname-unsigned-int-applicationversion-char-contenttopicname-char-encoding)
pub fn waku_create_content_topic(
application_name: &str,
application_version: usize,
@ -24,11 +34,13 @@ pub fn waku_create_content_topic(
))
}
.to_str()
.expect("&str from result should always be")
.expect("&str from result should always be extracted")
.parse()
.expect("Content topic data should be always parseable")
}
/// Create a pubsub topic string according to [RFC 23](https://rfc.vac.dev/spec/23/)
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_pubsub_topicchar-name-char-encoding)
pub fn waku_create_pubsub_topic(topic_name: &str, enconding: Encoding) -> WakuPubSubTopic {
unsafe {
CStr::from_ptr(waku_sys::waku_pubsub_topic(
@ -41,7 +53,138 @@ pub fn waku_create_pubsub_topic(topic_name: &str, enconding: Encoding) -> WakuPu
))
}
.to_str()
.expect("&str from result should always be")
.expect("&str from result should always be extracted")
.parse()
.expect("Pubsub topic data should be always parseable")
}
/// Default pubsub topic used for exchanging waku messages defined in [RFC 10](https://rfc.vac.dev/spec/10/)
pub fn waku_dafault_pubsub_topic() -> WakuPubSubTopic {
unsafe { CStr::from_ptr(waku_sys::waku_default_pubsub_topic()) }
.to_str()
.expect("&str from result should always be extracted")
.parse()
.expect("Default pubsub topic should always be parseable")
}
/// Publish a message using Waku Relay
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_relay_publishchar-messagejson-char-pubsubtopic-int-timeoutms)
pub fn waku_relay_publish_message(
message: &WakuMessage,
pubsub_topic: Option<&str>,
timeout: Duration,
) -> Result<MessageId> {
let pubsub_topic = pubsub_topic
.map(ToString::to_string)
.unwrap_or_else(|| waku_dafault_pubsub_topic().to_string());
let result = unsafe {
CStr::from_ptr(waku_sys::waku_relay_publish(
CString::new(
serde_json::to_string(&message)
.expect("WakuMessages should always be able to success serializing"),
)
.expect("CString should build properly from the serialized waku message")
.into_raw(),
CString::new(pubsub_topic)
.expect("CString should build properly from pubsub topic")
.into_raw(),
timeout
.as_millis()
.try_into()
.expect("Duration as milliseconds should fit in a i32"),
))
}
.to_str()
.expect("&str from result should always be extracted");
let message_id: JsonResponse<MessageId> =
serde_json::from_str(result).expect("JsonResponse should always succeed to deserialize");
message_id.into()
}
/// Optionally sign, encrypt using asymmetric encryption and publish a message using Waku Relay
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_relay_publish_enc_asymmetricchar-messagejson-char-pubsubtopic-char-publickey-char-optionalsigningkey-int-timeoutms)
pub fn waku_relay_publish_encrypt_asymmetric(
message: &WakuMessage,
pubsub_topic: Option<&str>,
public_key: &PublicKey,
signing_key: &SecretKey,
timeout: Duration,
) -> Result<MessageId> {
let pk = hex::encode(public_key.serialize());
let sk = hex::encode(signing_key.serialize());
let pubsub_topic = pubsub_topic
.map(ToString::to_string)
.unwrap_or_else(|| waku_dafault_pubsub_topic().to_string());
let result = unsafe {
CStr::from_ptr(waku_sys::waku_relay_publish_enc_asymmetric(
CString::new(
serde_json::to_string(&message)
.expect("WakuMessages should always be able to success serializing"),
)
.expect("CString should build properly from the serialized waku message")
.into_raw(),
CString::new(pubsub_topic)
.expect("CString should build properly from pubsub topic")
.into_raw(),
CString::new(pk)
.expect("CString should build properly from hex encoded public key")
.into_raw(),
CString::new(sk)
.expect("CString should build properly from hex encoded signing key")
.into_raw(),
timeout
.as_millis()
.try_into()
.expect("Duration as milliseconds should fit in a i32"),
))
.to_str()
.expect("Response should always succeed to load to a &str")
};
let message_id: JsonResponse<MessageId> =
serde_json::from_str(result).expect("JsonResponse should always succeed to deserialize");
message_id.into()
}
/// Optionally sign, encrypt using symmetric encryption and publish a message using Waku Relay
/// As per the [specification](https://rfc.vac.dev/spec/36/#extern-char-waku_relay_publish_enc_symmetricchar-messagejson-char-pubsubtopic-char-symmetrickey-char-optionalsigningkey-int-timeoutms)
pub fn waku_relay_publish_encrypt_symmetric(
message: &WakuMessage,
pubsub_topic: Option<&str>,
symmetric_key: &Key<Aes256Gcm>,
signing_key: &SecretKey,
timeout: Duration,
) -> Result<MessageId> {
let symk = hex::encode(symmetric_key.as_slice());
let sk = hex::encode(signing_key.serialize());
let pubsub_topic = pubsub_topic
.map(ToString::to_string)
.unwrap_or_else(|| waku_dafault_pubsub_topic().to_string());
let result = unsafe {
CStr::from_ptr(waku_sys::waku_relay_publish_enc_symmetric(
CString::new(
serde_json::to_string(&message)
.expect("WakuMessages should always be able to success serializing"),
)
.expect("CString should build properly from the serialized waku message")
.into_raw(),
CString::new(pubsub_topic)
.expect("CString should build properly from pubsub topic")
.into_raw(),
CString::new(symk)
.expect("CString should build properly from hex encoded symmetric key")
.into_raw(),
CString::new(sk)
.expect("CString should build properly from hex encoded signing key")
.into_raw(),
timeout
.as_millis()
.try_into()
.expect("Duration as milliseconds should fit in a i32"),
))
.to_str()
.expect("Response should always succeed to load to a &str")
};
let message_id: JsonResponse<MessageId> =
serde_json::from_str(result).expect("JsonResponse should always succeed to deserialize");
message_id.into()
}