Skip to content

Commit

Permalink
v0.9 (#37)
Browse files Browse the repository at this point in the history
polyproto v0.9 is here, and it is by far the biggest and best update to
the polyproto crate so far. It is the first version of the polyproto
crate which I am personally happy with, and which I can recommend to be
used by other people in their applications. This version is responsible
for a myriad of improvements to the polyproto API, which is now mostly
stable!

Here is a rundown of what has been changed, added and fixed:

## Additions

- More robust and wide-reaching tests, covering more cases, thus
uncovering bugs that desperately needed fixing
- Full HTTP API client for polyproto, gated behind `reqwest` feature
- Ergonomic API types gated behind `types` feature to use in own
applications
- serde support for der, spki and x509_cert types which directly
interface with the API

## Changes

- Made API more ergonomic
- Too many small ones to list :P

## Fixes

- Fixed catastrophically incorrect validation of IdCerts and IdCsrs
- Fixed incorrect parsing of BitStrings when converting to/from the
Capabilities struct
- Probably others I cannot recall right now
  • Loading branch information
bitfl0wer authored Jun 5, 2024
2 parents 88a1ab6 + a993b10 commit cac34f3
Show file tree
Hide file tree
Showing 59 changed files with 4,603 additions and 859 deletions.
44 changes: 21 additions & 23 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: ["main"]
pull_request:
branches: ["main", "dev"]
branches: ["*"]

env:
CARGO_TERM_COLOR: always
Expand All @@ -30,25 +30,23 @@ jobs:
cargo build --verbose --all-features
cargo test --verbose --all-features --tests --examples
fi
wasm:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
with:
cache-all-crates: "true"
prefix-key: "macos"
- name: Run WASM tests with Safari, Firefox, Chrome
run: |
rustup target add wasm32-unknown-unknown
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
cargo binstall --no-confirm wasm-bindgen-cli --version "0.2.88" --force
cargo binstall --no-confirm wasm-pack --force
wasm-pack test --node -- --features wasm --examples
wasm-pack test --firefox -- --features wasm --examples
wasm-pack test --chrome -- --features wasm --examples
wasm-pack test --safari -- --features wasm --examples
wasm-pack test --node -- --features wasm
wasm-pack test --firefox -- --features wasm
wasm-pack test --chrome -- --features wasm
wasm-pack test --safari -- --features wasm
# wasm:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: Swatinem/rust-cache@v2
# with:
# cache-all-crates: "true"
# prefix-key: "macos"
# - name: Run WASM tests with Safari, Firefox, Chrome
# run: |
# rustup target add wasm32-unknown-unknown
# curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
# cargo binstall --no-confirm wasm-bindgen-cli --version "0.2.88" --force
# cargo binstall --no-confirm wasm-pack --force
# wasm-pack test --node -- --features wasm --examples
# wasm-pack test --firefox -- --features wasm --examples
# wasm-pack test --chrome -- --features wasm --examples
# wasm-pack test --node -- --features wasm
# wasm-pack test --firefox -- --features wasm
# wasm-pack test --chrome -- --features wasm
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
.VSCodeCounter
.coverage
cert.csr
cert.der
cert.der
/firedbg
1 change: 1 addition & 0 deletions .vscode/ltex.dictionary.en-US.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ extnValue
extnID
CSRs
IdCsrInner
TryFrom
5 changes: 5 additions & 0 deletions .vscode/ltex.hiddenFalsePositives.en-US.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@
{"rule":"UNLIKELY_OPENING_PUNCTUATION","sentence":"^\\Q:3\\E$"}
{"rule":"DOUBLE_PUNCTUATION","sentence":"^\\QExtensions ::= SEQUENCE SIZE (1..MAX) OF Extension\\E$"}
{"rule":"COMMA_PARENTHESIS_WHITESPACE","sentence":"^\\QExtension ::= SEQUENCE {\nextnID OBJECT IDENTIFIER,\ncritical BOOLEAN DEFAULT FALSE,\nextnValue OCTET STRING\n-- contains the DER encoding of an ASN.1 value\n-- corresponding to the extension type identified\n-- by extnID\n}\\E$"}
{"rule":"MORFOLOGIK_RULE_EN_US","sentence":"^\\QResponse counterpart of CreateSessionSchema.\\E$"}
{"rule":"MASS_AGREEMENT","sentence":"^\\QThe challenge string.\\E$"}
{"rule":"MORFOLOGIK_RULE_EN_US","sentence":"^\\QResponse counterpart of IdentifyRequest.\\E$"}
{"rule":"EN_A_VS_AN","sentence":"^\\QTry to convert the inner byte slice to a u128.\\E$"}
{"rule":"POSSESSIVE_APOSTROPHE","sentence":"^\\QView the examples directory for a simple example on how to implement and use this crate with the ED25519 signature algorithm.\\E$"}
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"markiscodecoverage.searchCriteria": ".coverage/lcov*.info"
"markiscodecoverage.searchCriteria": ".coverage/lcov*.info",
"rust-analyzer.cargo.features": ["types", "reqwest"]
}
36 changes: 26 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,32 +1,48 @@
[package]
name = "polyproto"
version = "0.9.0-alpha.1"
version = "0.9.0"
edition = "2021"
license = "MPL-2.0"
description = "(Generic) Rust types and traits to quickly get a polyproto implementation up and running"
repository = "https://github.com/polyphony-chat/polyproto"
rust-version = "1.65.0"
rust-version = "1.71.1"

[lib]
crate-type = ["rlib", "cdylib", "staticlib"]

[features]
default = ["types"]
wasm = ["getrandom", "getrandom/js"]
getrandom = ["dep:getrandom"]
types = ["dep:http"]
reqwest = ["dep:reqwest", "types", "serde", "dep:url"]
serde = ["dep:serde", "dep:serde_json"]

[dependencies]
der = { version = "0.7.8", features = ["pem"] }
getrandom = { version = "0.2.12", optional = true }
der = { version = "0.7.9", features = ["pem"] }
getrandom = { version = "0.2.14", optional = true }
regex = "1.10.4"
spki = "0.7.3"
thiserror = "1.0.57"
x509-cert = { version = "0.2.5", default-features = false }
reqwest = { version = "0.12.4", features = ["json"], optional = true }
serde = { version = "1.0.199", optional = true, features = ["derive"] }
serde_json = { version = "1.0.116", optional = true }
spki = { version = "0.7.3", features = ["pem"] }
thiserror = "1.0.59"
x509-cert = "0.2.5"
log = "0.4.21"
url = { version = "2.5.0", optional = true }
http = { version = "1.1.0", optional = true }

[dev-dependencies]
ed25519-dalek = { version = "2.1.1", features = ["rand_core", "signature"] }
env_logger = "0.11.3"
httptest = "0.16.1"
rand = "0.8.5"
polyproto = { path = "./" }
tokio = { version = "1.37.0", features = ["full"] }
serde = { version = "1.0.199", features = ["derive"] }
serde_json = { version = "1.0.116" }
serde_test = "1.0.176"
polyproto = { path = "./", features = ["types", "reqwest", "serde"] }

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.3.39"
wasm-bindgen = "0.2.89"
wasm-bindgen-test = "0.3.42"
wasm-bindgen = "0.2.92"
41 changes: 32 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@

Crate supplying (generic) Rust types and traits to quickly get a
[polyproto](https://docs.polyphony.chat/Protocol%20Specifications/core/) implementation up and
running.
running, as well as an HTTP client for the polyproto API.

## Implementing polyproto
Building upon types offered by the [der](https://crates.io/crates/der),
[x509_cert](https://crates.io/crates/x509_cert) and [spki](https://crates.io/crates/spki) crates,
this crate provides a set of types and traits to quickly implement the polyproto specification.
Simply add cryptography and signature algorithm crates of your choice to the mix, and you are ready
to go.

**The crate is currently in an alpha stage. Some functionality is missing, and
things may break or change at any point in time.**
All polyproto certificate types can be converted to and from the types offered by the `x509_cert`
crate.

This crate extends upon types offered by [der](https://crates.io/crates/der) and
[spki](https://crates.io/crates/spki). As such, these crates are required dependencies for
projects looking to implement polyproto.
## Implementing polyproto

Start by implementing the trait [crate::signature::Signature] for a signature algorithm of your
choice. Popular crates for cryptography and signature algorithms supply their own `PublicKey` and
Expand All @@ -31,8 +33,8 @@ choice. Popular crates for cryptography and signature algorithms supply their ow
You can then use the [crate::certs] types to build certificates using your implementations of the
aforementioned traits.

View the [examples](./examples/) directory for a simple example on how to implement and use this
crate.
**View the [examples](./examples/)** directory for a simple example on how to implement and use this
crate with the ED25519 signature algorithm.

## Cryptography

Expand All @@ -41,6 +43,15 @@ implementing polyproto by transforming the
[polyproto specification](https://docs.polyphony.chat/Protocol%20Specifications/core/) into
well-defined yet adaptable Rust types.

## Safety

Please refer to the documentation of individual functions for information on which safety guarantees
they provide. Methods returning certificates, certificate requests and other types where the
validity and correctness of the data has a chance of impacting the security of a system always
mention the safety guarantees they provide in their respective documentation.

This crate has not undergone any security audits.

## WebAssembly

This crate is designed to work with the `wasm32-unknown-unknown` target. To compile for `wasm`, you
Expand All @@ -51,6 +62,18 @@ will have to use the `wasm` feature:
polyproto = { version = "0", features = ["wasm"] }
```

## HTTP API client through `reqwest`

If the `reqwest` feature is activated, this crate offers a polyproto HTTP API client, using the
`reqwest` crate.

### Alternatives to `reqwest`

If you would like to implement an HTTP client using something other than `reqwest`, simply enable
the `types` and `serde` features. Using these features, you can implement your own HTTP client, with
the polyproto crate acting as a single source of truth for request and response types, as well as
request routes and methods through the exported `static` `Route`s.

[build-shield]: https://img.shields.io/github/actions/workflow/status/polyphony-chat/polyproto/build_and_test.yml?style=flat
[build-url]: https://github.com/polyphony-chat/polyproto/blob/main/.github/workflows/build_and_test.yml
[coverage-shield]: https://coveralls.io/repos/github/polyphony-chat/polyproto/badge.svg?branch=main
Expand Down
24 changes: 12 additions & 12 deletions examples/ed25519_basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
// This example is not complete and should not be copy-pasted into a production environment without
// further scrutiny and consideration.

#![allow(unused)]

use std::str::FromStr;

use der::asn1::BitString;
Expand All @@ -17,10 +15,7 @@ use polyproto::key::{PrivateKey, PublicKey};
use polyproto::signature::Signature;
use rand::rngs::OsRng;
use spki::{AlgorithmIdentifierOwned, ObjectIdentifier, SignatureBitStringEncoding};
use thiserror::Error;

#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
#[cfg_attr(not(target_arch = "wasm32"), test)]
fn main() {
let mut csprng = rand::rngs::OsRng;
// Generate a key pair
Expand Down Expand Up @@ -60,10 +55,6 @@ fn main() {
)
}

#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(test))]
fn main() {}

// As mentioned in the README, we start by implementing the signature trait.

// Here, we start by defining the signature type, which is a wrapper around the signature type from
Expand All @@ -74,6 +65,12 @@ struct Ed25519Signature {
algorithm: AlgorithmIdentifierOwned,
}

impl std::fmt::Display for Ed25519Signature {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.signature)
}
}

// We implement the Signature trait for our signature type.
impl Signature for Ed25519Signature {
// We define the signature type from the ed25519-dalek crate as the associated type.
Expand All @@ -96,7 +93,7 @@ impl Signature for Ed25519Signature {
}

#[cfg(not(tarpaulin_include))]
fn from_bitstring(signature: &[u8]) -> Self {
fn from_bytes(signature: &[u8]) -> Self {
let mut signature_vec = signature.to_vec();
signature_vec.resize(64, 0);
let signature_array: [u8; 64] = {
Expand Down Expand Up @@ -196,8 +193,6 @@ impl PublicKey<Ed25519Signature> for Ed25519PublicKey {
fn try_from_public_key_info(
public_key_info: PublicKeyInfo,
) -> Result<Self, polyproto::errors::composite::ConversionError> {
use polyproto::errors::composite::ConversionError;

let mut key_vec = public_key_info.public_key_bitstring.raw_bytes().to_vec();
key_vec.resize(32, 0);
let signature_array: [u8; 32] = {
Expand All @@ -210,3 +205,8 @@ impl PublicKey<Ed25519Signature> for Ed25519PublicKey {
})
}
}

#[test]
fn test_example() {
main()
}
Loading

0 comments on commit cac34f3

Please sign in to comment.