Skip to content

Commit

Permalink
Bump plexi_core and plexi_cli
Browse files Browse the repository at this point in the history
Also add a readme
  • Loading branch information
thibmeu committed Sep 6, 2024
1 parent 8ee904c commit cc61b43
Show file tree
Hide file tree
Showing 6 changed files with 329 additions and 34 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

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

18 changes: 5 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,30 @@ authors = [
edition = "2021"
readme = "README.md"
homepage = "https://github.com/cloudflare/plexi"
repository = "https://github.com/thibmeu/plexi"
repository = "https://github.com/cloudflare/plexi"
keywords = ["transparency", "e2ee", "auditor", "cryptography"]
categories = ["cryptography"]
license = "Apache-2.0"

[workspace.dependencies]
akd = { version = "0.11", default-features = false }
anyhow = "1.0"
bincode = "2.0.0-rc.3"
bytes = "1.6"
console_error_panic_hook = { version = "0.1" }
clap = { version = "4.5", features = ["derive"] }
clap-verbosity-flag = "2.2.0"
env_logger = { version = "0.11" }
ed25519-dalek = { version = "2" }
futures-util = "0.3"
getrandom = "0.2"
hex = { version = "0.4" }
matchit = "0.8"
prost = "0.13"
prometheus = "0.13"
rand = { version = "0.8", default-features = false, features = ["getrandom"] }
protobuf = "3.2"
serde = "1.0"
serde_json = "1.0"
sha2 = "0.10"
thiserror = { version = "1.0" }
tokio = "1.0"
utoipa = "4"
utoipa-redoc = "4"
uuid = { version = "1.9", features = ["v4", "serde"] }
worker = "0.3.1"
tracing = "0.1"
tracing-web = "0.1"
tracing-subscriber = { version = "0.3", features=['time', 'json'] }
time = { version = "0.3", features=['wasm-bindgen'] }

# workspace dependencies
plexi_core = { path = "./plexi_core" }
Expand Down
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# plexi

Plexi is a flexible auditor for [Transparency systems](https://blog.cloudflare.com/key-transparency).

This software has not been audited. Please use at your sole discretion.

## Feature highlights
* Verify [akd](https://github.com/facebook/akd) based signatures

## Installation

| Environment | CLI Command |
|:-------------------|:--------------------------------------------------------------------------------|
| Cargo (Rust 1.74+) | `cargo install plexi_cli --git https://github.com/cloudflare/plexi --bin plexi` |

## Usage

### Verify akd signature

Once the namespace and the epoch is set, the following command should return `Signature valid`.

```shell
NAMESPACE="test.whatsapp.key-transparency.v1"
EPOCH="434592"
AUDITOR_PUBLIC_KEY="$(curl -sS 'https://akd-auditor.cloudflare.com/info' | jq -r '.keys[0].public_key')"

curl -sS "https://akd-auditor.cloudflare.com/namespaces/${NAMESPACE}/audits/${EPOCH}" | \
plexi verify --namespace "${NAMESPACE}" --publickey "${AUDITOR_PUBLIC_KEY}"
```

## Contributing
Please see our [contribution guidelines](./.github/CONTRIBUTING.md).

## License
This project is Licensed under [Apache License, Version 2.0](./LICENSE).
4 changes: 1 addition & 3 deletions plexi_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@ ed25519-dalek = { workspace = true }
hex = { workspace = true, features = ["serde"] }
prost = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
thiserror = { workspace = true }
utoipa = { workspace = true, optional = true }
uuid = { workspace = true, features = ["v4", "serde"] }

[dev-dependencies]
serde_json = { workspace = true }

[build-dependencies]
prost-build = { version = "0.13" }
140 changes: 124 additions & 16 deletions plexi_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ use serde::{Deserialize, Serialize};
use thiserror::Error;
#[cfg(feature = "openapi")]
use utoipa::ToSchema;
use uuid::Uuid;

pub use uuid::Uuid;

pub mod crypto;
pub mod namespaces;
pub mod proto;

const SIGNATURE_VERSIONS: [SignatureVersion; 2] = [
Expand All @@ -32,9 +34,11 @@ pub enum PlexiError {
MissingParameter(String),
#[error("cannot serialize message")]
Serialization,
#[error("Root is not valid")]
InvalidRoot,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(into = "u32")]
#[serde(from = "u32")]
Expand Down Expand Up @@ -90,7 +94,7 @@ impl Encode for SignatureVersion {
&self,
encoder: &mut E,
) -> Result<(), bincode::error::EncodeError> {
let value: u32 = self.clone().into();
let value: u32 = (*self).into();
bincode::Encode::encode(&value, encoder)
}
}
Expand All @@ -113,7 +117,7 @@ impl<'de> BorrowDecode<'de> for SignatureVersion {
}
}

#[derive(Clone, Debug, Serialize, Deserialize, Encode, Decode)]
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Encode, Decode)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct Epoch(u64);

Expand All @@ -131,6 +135,18 @@ impl From<&Epoch> for u64 {
}
}

impl From<Epoch> for u64 {
fn from(val: Epoch) -> Self {
val.0
}
}

impl From<u64> for Epoch {
fn from(val: u64) -> Self {
Epoch(val)
}
}

impl fmt::Display for Epoch {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
Expand Down Expand Up @@ -215,10 +231,10 @@ impl SignatureMessage {
return Err(PlexiError::BadParameter("version".to_string()));
}
Ok(Self {
version: version.clone(),
version: *version,
namespace,
timestamp,
epoch: epoch.clone(),
epoch: *epoch,
digest,
})
}
Expand Down Expand Up @@ -250,11 +266,11 @@ impl SignatureMessage {

fn to_vec_proto(&self) -> Result<Vec<u8>, PlexiError> {
let message = proto::types::SignatureMessage {
version: self.version().clone().into(),
version: (*self.version()).into(),
namespace: self.namespace().to_string(),
timestamp: self.timestamp(),
epoch: proto::types::Epoch {
inner: Some(self.epoch().into()),
inner: self.epoch().into(),
},
digest: self.digest().clone(),
};
Expand Down Expand Up @@ -303,7 +319,7 @@ impl From<SignatureMetadata> for HashMap<String, String> {
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct SignatureRequest {
epoch: Epoch,
Expand All @@ -318,15 +334,24 @@ impl SignatureRequest {
}

pub fn epoch(&self) -> Epoch {
self.epoch.clone()
self.epoch
}

pub fn digest(&self) -> Vec<u8> {
self.digest.clone()
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
impl fmt::Debug for SignatureRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SignatureRequest")
.field("epoch", &self.epoch)
.field("digest", &hex::encode(&self.digest))
.finish()
}
}

#[derive(Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct SignatureResponse {
version: SignatureVersion,
Expand All @@ -341,6 +366,20 @@ pub struct SignatureResponse {
key_id: Option<u8>,
}

impl fmt::Debug for SignatureResponse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SignatureResponse")
.field("version", &self.version)
.field("namespace", &self.namespace)
.field("timestamp", &self.timestamp)
.field("epoch", &self.epoch)
.field("digest", &hex::encode(&self.digest))
.field("signature", &hex::encode(&self.signature))
.field("key_id", &self.key_id)
.finish()
}
}

impl SignatureResponse {
pub fn new(
version: &SignatureVersion,
Expand All @@ -352,10 +391,10 @@ impl SignatureResponse {
key_id: Option<u8>,
) -> Self {
Self {
version: version.clone(),
version: *version,
namespace,
timestamp,
epoch: epoch.clone(),
epoch: *epoch,
digest,
signature,
key_id,
Expand Down Expand Up @@ -383,7 +422,10 @@ impl SignatureResponse {
}

pub fn signature(&self) -> [u8; SIGNATURE_LENGTH] {
self.signature.as_slice().try_into().unwrap()
self.signature
.as_slice()
.try_into()
.expect("signature bytes have a known length")
}

pub fn key_id(&self) -> Option<u8> {
Expand All @@ -397,7 +439,7 @@ pub type Report = SignatureResponse;
impl From<Report> for HashMap<String, String> {
fn from(val: Report) -> Self {
let mut map = HashMap::new();
let version: u32 = val.version().clone().into();
let version: u32 = (*val.version()).into();
map.insert("version".to_string(), version.to_string());
map.insert("namespace".to_string(), val.namespace().to_string());
map.insert("timestamp".to_string(), val.timestamp.to_string());
Expand Down Expand Up @@ -446,7 +488,11 @@ impl TryFrom<HashMap<String, String>> for Report {
.ok_or_else(|| PlexiError::MissingParameter("signature".to_string()))?,
)
.map_err(|_| PlexiError::BadParameter("signature".to_string()))?,
key_id: value.get("key_id").map(|id| id.parse().unwrap()),
key_id: value
.get("key_id")
.map(|id| id.parse())
.transpose()
.map_err(|_| PlexiError::BadParameter("key_id".to_string()))?,
})
}
}
Expand All @@ -471,6 +517,68 @@ impl ReportResponse {
}
}

#[derive(Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct LastVerifiedEpoch {
job_id: Uuid,
epoch: Epoch,
#[serde(with = "hex::serde")]
start_hash: Vec<u8>,
#[serde(with = "hex::serde")]
end_hash: Vec<u8>,
timestamp: u64,
}

impl fmt::Debug for LastVerifiedEpoch {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LastVerifiedEpoch")
.field("job_id", &self.job_id)
.field("epoch", &self.epoch)
.field("start_hash", &hex::encode(&self.start_hash))
.field("end_hash", &hex::encode(&self.end_hash))
.field("timestamp", &self.timestamp)
.finish()
}
}

impl LastVerifiedEpoch {
pub fn new(
job_id: Uuid,
epoch: Epoch,
start_hash: Vec<u8>,
end_hash: Vec<u8>,
timestamp: u64,
) -> Self {
Self {
job_id,
epoch,
start_hash,
end_hash,
timestamp,
}
}

pub fn job_id(&self) -> Uuid {
self.job_id
}

pub fn epoch(&self) -> Epoch {
self.epoch
}

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

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

pub fn timestamp(&self) -> u64 {
self.timestamp
}
}

#[cfg(test)]
mod tests {
use crypto::ed25519_public_key_to_key_id;
Expand Down
Loading

0 comments on commit cc61b43

Please sign in to comment.