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

Migrate to coset and ciborium #94

Merged
merged 20 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e849575
seerialize cose objects with serde and ciborium for serde
radumarias Sep 6, 2024
8eac14f
remove serde_cbor and use coset and ciborium serialization and CborValue
radumarias Sep 7, 2024
369c1a3
remove serde_cbor and use coset and ciborium serialization and CborValue
radumarias Sep 7, 2024
178edf7
clippy
radumarias Sep 7, 2024
7d90847
Add MaybeTagged struct and wrap Cose objects in that
radumarias Sep 7, 2024
ccaae0b
Add MaybeTagged struct and wrap Cose objects in that
radumarias Sep 7, 2024
670bce2
use correct TAG in MaybeTagged when serializing
radumarias Sep 9, 2024
0c6efb5
handle the case of non-finite floats
radumarias Sep 11, 2024
55ff9af
handle the case of non-finite floats
radumarias Sep 11, 2024
d08601c
adapt to impl TryFrom<ciborium::Value> for Value
radumarias Sep 11, 2024
c796aa6
adapt to impl TryFrom<ciborium::Value> for Value
radumarias Sep 11, 2024
9fe82d8
Don't use cbor::Value but use directly ciborium::Value and use keys a…
radumarias Sep 16, 2024
923408c
Don't use cbor::Value but use directly ciborium::Value and use keys a…
radumarias Sep 16, 2024
9b770b6
consume self in into_ method
radumarias Sep 16, 2024
378ded9
Merge branch 'main' into coset
radumarias Sep 16, 2024
4a979b6
fmt
radumarias Sep 16, 2024
bf0702e
Update .github/workflows/ci.yaml
radumarias Sep 18, 2024
890a199
fix minor issues
radumarias Sep 19, 2024
323e62b
borError wraps coset::CoseError and impl std::Error and Display, and …
radumarias Sep 22, 2024
ba0ec62
Update macros/src/to_cbor.rs
radumarias Sep 23, 2024
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
7 changes: 7 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: setup Rust
uses: dtolnay/rust-toolchain@stable
if: ${{ github.event.act }}
with:
toolchain: stable
components: rustfmt, clippy

- name: Build
run: cargo build --all-targets

Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/event.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"act": true
}
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ p256 = { version = "0.13.0", features = ["serde", "ecdh"] }
p384 = { version = "0.13.0", features = ["serde", "ecdh"] }
rand = { version = "0.8.5", features = ["getrandom"] }
serde = { version = "1.0", features = ["derive"] }
serde_cbor = { version = "0.11.2", features = ["tags"] }
serde_json = "1.0"
serde_bytes = "0.11.0"
sha2 = "0.10.6"
thiserror = "1.0"
elliptic-curve = "0.13.1"
Expand Down Expand Up @@ -46,9 +46,9 @@ clap-stdin = "0.2.1"
strum = "0.24"
strum_macros = "0.24"

[dependencies.cose-rs]
git = "https://github.com/spruceid/cose-rs"
rev = "4104505"
coset = "0.3.8"
ciborium = "0.2.2"
digest = "0.10.7"

[dev-dependencies]
hex = "0.4.3"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,4 @@ stateDiagram

You can see the full example in [simulated_device_and_reader](tests/simulated_device_and_reader.rs) and a version that
uses `State` pattern, `Arc` and `Mutex` [simulated_device_and_reader](tests/simulated_device_and_reader_state.rs).

5 changes: 2 additions & 3 deletions macros/src/to_cbor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ fn named_fields(isomdl_path: Ident, ident: Ident, input: FieldsNamed) -> TokenSt

let output = quote! {
mod #mod_name {
use serde_cbor::Value;
use ciborium::Value;
use super::*;
use #isomdl_path::definitions::traits::{ToCbor, ToNamespaceMap};
impl ToNamespaceMap for #ident {
Expand Down Expand Up @@ -140,9 +140,8 @@ fn unnamed_fields(isomdl_path: Ident, ident: Ident, mut input: FieldsUnnamed) ->
mod #mod_name {
use super::*;
use #isomdl_path::definitions::traits::{ToCbor, ToCborError};
use serde_cbor::Value;
impl ToCbor for #ident {
fn to_cbor(self) -> Value {
fn to_cbor(self) -> ciborium::Value {
<#field_type as ToCbor>::to_cbor(self)
}
}
Expand Down
67 changes: 67 additions & 0 deletions src/cbor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use std::io::Cursor;

use ciborium::Value;
use coset::{cbor, CoseError};
use serde::{de, Serialize};
use std::error::Error;
use std::fmt;

pub fn to_vec<T>(value: &T) -> Result<Vec<u8>, CborError>
where
T: serde::Serialize,
{
let mut buf = Vec::new();
ciborium::into_writer(value, &mut buf).map_err(|_| CborError(CoseError::EncodeFailed))?;
Ok(buf)
}

pub fn from_slice<T>(slice: &[u8]) -> Result<T, CborError>
where
T: de::DeserializeOwned,
{
ciborium::from_reader(Cursor::new(&slice)).map_err(|e| {
CborError(CoseError::DecodeFailed(ciborium::de::Error::Semantic(
None,
e.to_string(),
)))
})
}

/// Convert a `ciborium::Value` into a type `T`
#[allow(clippy::needless_pass_by_value)]
pub fn from_value<T>(value: Value) -> Result<T, CoseError>
where
T: de::DeserializeOwned,
{
Value::deserialized(&value).map_err(|_| {
CoseError::DecodeFailed(cbor::de::Error::Semantic(
None,
"cannot deserialize".to_string(),
))
})
}

pub fn into_value<S>(v: S) -> Result<Value, CoseError>
where
S: Serialize,
{
Value::serialized(&v).map_err(|_| CoseError::EncodeFailed)
}

// Wrapper struct to implement Error for CoseError
#[derive(Debug)]
pub struct CborError(pub CoseError);

impl From<CoseError> for CborError {
fn from(err: CoseError) -> CborError {
CborError(err)
}
}

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

impl Error for CborError {}
127 changes: 127 additions & 0 deletions src/cose.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use std::borrow::{Borrow, BorrowMut};
use std::ops::{Deref, DerefMut};

use coset::{iana, AsCborValue, TaggedCborSerializable};

use crate::cose::serialized_as_cbor_value::SerializedAsCborValue;

pub mod mac0;
mod serialized_as_cbor_value;
pub mod sign1;

/// Trait to represent the signature algorithm of a signer or verifier.
pub trait SignatureAlgorithm {
fn algorithm(&self) -> iana::Algorithm;
}

#[derive(Debug, Clone)]
pub struct MaybeTagged<T>
where
T: AsCborValue + TaggedCborSerializable + Clone,
{
pub tagged: bool,
pub inner: T,
}

impl<T> MaybeTagged<T>
where
T: AsCborValue + TaggedCborSerializable + Clone,
{
pub fn new(tagged: bool, inner: T) -> Self {
Self { tagged, inner }
}

/// If we are serialized as tagged.
pub fn is_tagged(&self) -> bool {
self.tagged
}

/// Set serialization to tagged.
pub fn set_tagged(&mut self) {
self.tagged = true;
}
}

impl<T> Deref for MaybeTagged<T>
where
T: AsCborValue + TaggedCborSerializable + Clone,
{
type Target = T;

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

impl<T> DerefMut for MaybeTagged<T>
where
T: AsCborValue + TaggedCborSerializable + Clone,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}

impl<T> Borrow<T> for MaybeTagged<T>
where
T: AsCborValue + TaggedCborSerializable + Clone,
{
fn borrow(&self) -> &T {
&self.inner
}
}

impl<T> BorrowMut<T> for MaybeTagged<T>
where
T: AsCborValue + TaggedCborSerializable + Clone,
{
fn borrow_mut(&mut self) -> &mut T {
&mut self.inner
}
}

impl<T> AsRef<T> for MaybeTagged<T>
where
T: AsCborValue + TaggedCborSerializable + Clone,
{
fn as_ref(&self) -> &T {
&self.inner
}
}

/// Serialize manually using `ciborium::tag::Captured`, putting the tag if
/// necessary.
impl<T> serde::Serialize for MaybeTagged<T>
where
T: AsCborValue + TaggedCborSerializable + Clone,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let tag = if self.tagged { Some(T::TAG) } else { None };

ciborium::tag::Captured(tag, SerializedAsCborValue(&self.inner)).serialize(serializer)
}
}

/// Deserialize manually using `ciborium::tag::Captured`, checking the tag.
impl<'de, T> serde::Deserialize<'de> for MaybeTagged<T>
where
T: AsCborValue + TaggedCborSerializable + Clone,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let ciborium::tag::Captured(tag, SerializedAsCborValue(inner)) =
ciborium::tag::Captured::deserialize(deserializer)?;
let tagged = match tag {
Some(tag) if tag == T::TAG => true,
Some(_) => return Err(serde::de::Error::custom("unexpected tag")),
None => false,
};

Ok(Self { tagged, inner })
}
}
Loading