Skip to content

Commit

Permalink
Merge branch 'main' into feat/linked-verifiable-presentation
Browse files Browse the repository at this point in the history
  • Loading branch information
UMR1352 authored Sep 4, 2024
2 parents d061db4 + b355b47 commit f50cbe9
Show file tree
Hide file tree
Showing 17 changed files with 177 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .github/actions/iota-sandbox/tear-down/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ runs:
shell: bash
run: |
cd iota-sandbox/sandbox
docker-compose down
docker compose down
cd ../..
sudo rm -rf iota-sandbox
15 changes: 9 additions & 6 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,18 @@ jobs:
run: cargo clean

# Build the library, tests, and examples without running them to avoid recompilation in the run tests step
- name: Build with all features
run: cargo build --workspace --tests --examples --all-features --release
- name: Build with default features
run: cargo build --workspace --tests --examples --release

- name: Start iota sandbox
if: matrix.os == 'ubuntu-latest'
uses: './.github/actions/iota-sandbox/setup'

- name: Run tests
run: cargo test --workspace --all-features --release
- name: Run tests excluding `custom_time` feature
run: cargo test --workspace --release

- name: Run tests with `custom_time` feature
run: cargo test --test custom_time --features="custom_time"

- name: Run Rust examples
# run examples only on ubuntu for now
Expand All @@ -157,7 +160,7 @@ jobs:
- name: Tear down iota sandbox
if: matrix.os == 'ubuntu-latest' && always()
uses: './.github/actions/iota-sandbox/tear-down'

- name: Stop sccache
uses: './.github/actions/rust/sccache/stop-sccache'
with:
Expand Down Expand Up @@ -253,7 +256,7 @@ jobs:
load: true

- name: Run cypress
run: docker run --network host cypress-test test:browser:firefox
run: docker run --network host cypress-test test:browser:parallel:firefox

- name: Tear down iota sandbox
if: always()
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ members = [
exclude = ["bindings/wasm", "bindings/grpc"]

[workspace.dependencies]
bls12_381_plus = { version = "=0.8.15" }
bls12_381_plus = { version = "0.8.17" }
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
thiserror = { version = "1.0", default-features = false }
strum = { version = "0.25", default-features = false, features = ["std", "derive"] }
Expand Down
2 changes: 1 addition & 1 deletion bindings/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ crate-type = ["cdylib", "rlib"]

[dependencies]
async-trait = { version = "0.1", default-features = false }
bls12_381_plus = "=0.8.15"
bls12_381_plus = "0.8.17"
console_error_panic_hook = { version = "0.1" }
futures = { version = "0.3" }
identity_eddsa_verifier = { path = "../../identity_eddsa_verifier", default-features = false, features = ["ed25519"] }
Expand Down
10 changes: 8 additions & 2 deletions bindings/wasm/cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@ export default defineConfig({
},
e2e: {
supportFile: false,
// Fix to make subtle crypto work in cypress firefox
// https://github.com/cypress-io/cypress/issues/18217
setupNodeEvents(on, config) {
on("before:browser:launch", (browser, launchOptions) => {
if (browser.family === "firefox") {
// Fix to make subtle crypto work in cypress firefox
// https://github.com/cypress-io/cypress/issues/18217
launchOptions.preferences[
"network.proxy.testing_localhost_is_secure_when_hijacked"
] = true;
// Temporary fix to allow cypress to control Firefox via CDP
// https://github.com/cypress-io/cypress/issues/29713
// https://fxdx.dev/deprecating-cdp-support-in-firefox-embracing-the-future-with-webdriver-bidi/
launchOptions.preferences[
"remote.active-protocols"
] = 3;
}
return launchOptions;
});
Expand Down
11 changes: 9 additions & 2 deletions identity_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ rust-version.workspace = true
description = "The core traits and types for the identity-rs library."

[dependencies]
iota-crypto = { version = "0.23", default-features = false, features = ["ed25519", "random", "sha", "x25519", "std"] }
multibase = { version = "0.9", default-features = false, features = ["std"] }
serde = { workspace = true, features = ["std"] }
serde_json = { workspace = true, features = ["std"] }
Expand All @@ -22,7 +21,7 @@ time = { version = "0.3.23", default-features = false, features = ["std", "serde
url = { version = "2.4", default-features = false, features = ["serde"] }
zeroize = { version = "1.6", default-features = false }

[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies]
[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi"), not(feature = "custom_time")))'.dependencies]
js-sys = { version = "0.3.55", default-features = false }

[dev-dependencies]
Expand All @@ -38,3 +37,11 @@ rustdoc-args = ["--cfg", "docsrs"]

[lints]
workspace = true

[features]
# Enables a macro to provide a custom time (Timestamp::now_utc) implementation, see src/custom_time.rs
custom_time = []

[[test]]
name = "custom_time"
required-features = ["custom_time"]
16 changes: 14 additions & 2 deletions identity_core/src/common/timestamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ impl Timestamp {
/// fractional seconds truncated.
///
/// See the [`datetime` DID-core specification](https://www.w3.org/TR/did-core/#production).
#[cfg(not(all(target_arch = "wasm32", not(target_os = "wasi"))))]
#[cfg(all(
not(all(target_arch = "wasm32", not(target_os = "wasi"))),
not(feature = "custom_time")
))]
pub fn now_utc() -> Self {
Self(truncate_fractional_seconds(OffsetDateTime::now_utc()))
}
Expand All @@ -51,14 +54,23 @@ impl Timestamp {
/// fractional seconds truncated.
///
/// See the [`datetime` DID-core specification](https://www.w3.org/TR/did-core/#production).
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), not(feature = "custom_time")))]
pub fn now_utc() -> Self {
let milliseconds_since_unix_epoch: i64 = js_sys::Date::now() as i64;
let seconds: i64 = milliseconds_since_unix_epoch / 1000;
// expect is okay, we assume the current time is between 0AD and 9999AD
Self::from_unix(seconds).expect("Timestamp failed to convert system datetime")
}

/// Creates a new `Timestamp` with the current date and time, normalized to UTC+00:00 with
/// fractional seconds truncated.
///
/// See the [`datetime` DID-core specification](https://www.w3.org/TR/did-core/#production).
#[cfg(feature = "custom_time")]
pub fn now_utc() -> Self {
crate::custom_time::now_utc_custom()
}

/// Returns the `Timestamp` as an [RFC 3339](https://tools.ietf.org/html/rfc3339) `String`.
pub fn to_rfc3339(&self) -> String {
// expect is okay, constructors ensure RFC 3339 compatible timestamps.
Expand Down
88 changes: 88 additions & 0 deletions identity_core/src/custom_time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright 2020-2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

//! An implementation of `now_utc` which calls out to an externally defined function.
use crate::common::Timestamp;

/// Register a function to be invoked by `identity_core` in order to get a [Timestamp] representing
/// "now".
///
/// ## Writing a custom `now_utc` implementation
///
/// The function to register must have the same signature as
/// [`Timestamp::now_utc`](Timestamp::now_utc). The function can be defined
/// wherever you want, either in root crate or a dependent crate.
///
/// For example, if we wanted a `static_now_utc` crate containing an
/// implementation that always returns the same timestamp, we would first depend on `identity_core`
/// (for the [`Timestamp`] type) in `static_now_utc/Cargo.toml`:
/// ```toml
/// [dependencies]
/// identity_core = "1"
/// ```
/// Note that the crate containing this function does **not** need to enable the
/// `"custom_time"` Cargo feature.
///
/// Next, in `static_now_utc/src/lib.rs`, we define our function:
/// ```rust
/// use identity_core::common::Timestamp;
///
/// // Some fixed timestamp
/// const MY_FIXED_TIMESTAMP: i64 = 1724402964;
/// pub fn static_now_utc() -> Timestamp {
/// Timestamp::from_unix(MY_FIXED_TIMESTAMP).unwrap()
/// }
/// ```
///
/// ## Registering a custom `now_utc` implementation
///
/// Functions can only be registered in the root binary crate. Attempting to
/// register a function in a non-root crate will result in a linker error.
/// This is similar to
/// [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) or
/// [`#[global_allocator]`](https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/global-allocators.html),
/// where helper crates define handlers/allocators but only the binary crate
/// actually _uses_ the functionality.
///
/// To register the function, we first depend on `static_now_utc` _and_
/// `identity_core` in `Cargo.toml`:
/// ```toml
/// [dependencies]
/// static_now_utc = "0.1"
/// identity_core = { version = "1", features = ["custom_time"] }
/// ```
///
/// Then, we register the function in `src/main.rs`:
/// ```rust
/// # mod static_now_utc { pub fn static_now_utc() -> Timestamp { unimplemented!() } }
///
/// use identity_core::register_custom_now_utc;
/// use static_now_utc::static_now_utc;
///
/// register_custom_now_utc!(static_now_utc);
/// ```
///
/// Now any user of `now_utc` (direct or indirect) on this target will use the
/// registered function.
#[macro_export]
macro_rules! register_custom_now_utc {
($path:path) => {
const __GET_TIME_INTERNAL: () = {
// We use Rust ABI to be safe against potential panics in the passed function.
#[no_mangle]
unsafe fn __now_utc_custom() -> Timestamp {
// Make sure the passed function has the type of `now_utc_custom`
type F = fn() -> Timestamp;
let f: F = $path;
f()
}
};
};
}

pub(crate) fn now_utc_custom() -> Timestamp {
extern "Rust" {
fn __now_utc_custom() -> Timestamp;
}
unsafe { __now_utc_custom() }
}
7 changes: 6 additions & 1 deletion identity_core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright 2020-2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]
#![doc = include_str!("./../README.md")]
#![allow(clippy::upper_case_acronyms)]
#![warn(
Expand All @@ -19,9 +18,15 @@
#[doc(inline)]
pub use serde_json::json;

#[forbid(unsafe_code)]
pub mod common;
#[forbid(unsafe_code)]
pub mod convert;
#[forbid(unsafe_code)]
pub mod error;

#[cfg(feature = "custom_time")]
pub mod custom_time;

pub use self::error::Error;
pub use self::error::Result;
18 changes: 18 additions & 0 deletions identity_core/tests/custom_time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2020-2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use identity_core::common::Timestamp;
use identity_core::register_custom_now_utc;

const STATIC_TIME: i64 = 1724402964; // 2024-08-23T11:33:30+00:00
pub fn static_now_utc() -> Timestamp {
Timestamp::from_unix(STATIC_TIME).unwrap()
}

register_custom_now_utc!(static_now_utc);

#[test]
fn should_use_registered_static_time() {
let timestamp = Timestamp::now_utc();
assert_eq!(timestamp.to_unix(), STATIC_TIME)
}
2 changes: 1 addition & 1 deletion identity_credential/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ zkryptium = { workspace = true, optional = true }
[dev-dependencies]
anyhow = "1.0.62"
identity_eddsa_verifier = { path = "../identity_eddsa_verifier", default-features = false, features = ["ed25519"] }
iota-crypto = { version = "0.23", default-features = false, features = ["ed25519", "std", "random"] }
iota-crypto = { version = "0.23.2", default-features = false, features = ["ed25519", "std", "random"] }
proptest = { version = "1.4.0", default-features = false, features = ["std"] }
tokio = { version = "1.35.0", default-features = false, features = ["rt-multi-thread", "macros"] }

Expand Down
2 changes: 1 addition & 1 deletion identity_eddsa_verifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ description = "JWS EdDSA signature verification for IOTA Identity"

[dependencies]
identity_jose = { version = "=1.3.1", path = "../identity_jose", default-features = false }
iota-crypto = { version = "0.23", default-features = false, features = ["std"] }
iota-crypto = { version = "0.23.2", default-features = false, features = ["std"] }

[features]
ed25519 = ["iota-crypto/ed25519"]
Expand Down
2 changes: 1 addition & 1 deletion identity_iota_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ thiserror.workspace = true

[dev-dependencies]
anyhow = { version = "1.0.57" }
iota-crypto = { version = "0.23", default-features = false, features = ["bip39", "bip39-en"] }
iota-crypto = { version = "0.23.2", default-features = false, features = ["bip39", "bip39-en"] }
proptest = { version = "1.0.0", default-features = false, features = ["std"] }
tokio = { version = "1.29.0", default-features = false, features = ["rt-multi-thread", "macros"] }

Expand Down
4 changes: 2 additions & 2 deletions identity_jose/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ description = "A library for JOSE (JSON Object Signing and Encryption)"
[dependencies]
bls12_381_plus.workspace = true
identity_core = { version = "=1.3.1", path = "../identity_core", default-features = false }
iota-crypto = { version = "0.23", default-features = false, features = ["std", "sha"] }
iota-crypto = { version = "0.23.2", default-features = false, features = ["std", "sha"] }
json-proof-token.workspace = true
serde.workspace = true
serde_json = { version = "1.0", default-features = false, features = ["std"] }
Expand All @@ -24,7 +24,7 @@ zeroize = { version = "1.6", default-features = false, features = ["std", "zeroi

[dev-dependencies]
anyhow = "1"
iota-crypto = { version = "0.23", features = ["ed25519", "random", "hmac"] }
iota-crypto = { version = "0.23.2", features = ["ed25519", "random", "hmac"] }
p256 = { version = "0.12.0", default-features = false, features = ["std", "ecdsa", "ecdsa-core"] }
signature = { version = "2", default-features = false }

Expand Down
5 changes: 3 additions & 2 deletions identity_jose/src/tests/rfc8037.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ fn test_rfc8037_ed25519() {
.and_then(|decoded| decoded.verify(&jws_verifier, &public))
.unwrap();

assert_eq!(token.protected, header);
assert_eq!(token.claims, tv.payload.as_bytes());

let jws_signature_verifier = JwsVerifierFn::from(|input: VerificationInput, key: &Jwk| match input.alg {
JwsAlgorithm::EdDSA => ed25519::verify(input, key),
other => unimplemented!("{other}"),
Expand All @@ -62,7 +65,5 @@ fn test_rfc8037_ed25519() {
.unwrap();

assert_eq!(token, token_with_default);
assert_eq!(token.protected, header);
assert_eq!(token.claims, tv.payload.as_bytes());
}
}
9 changes: 7 additions & 2 deletions identity_storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ identity_did = { version = "=1.3.1", path = "../identity_did", default-features
identity_document = { version = "=1.3.1", path = "../identity_document", default-features = false }
identity_iota_core = { version = "=1.3.1", path = "../identity_iota_core", default-features = false, optional = true }
identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false }
iota-crypto = { version = "0.23", default-features = false, features = ["ed25519"], optional = true }
iota-crypto = { version = "0.23.2", default-features = false, features = ["ed25519", "random"], optional = true }
json-proof-token = { workspace = true, optional = true }
rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"], optional = true }
seahash = { version = "4.1.0", default-features = false }
Expand All @@ -47,7 +47,12 @@ send-sync-storage = []
# Implements the JwkStorageDocumentExt trait for IotaDocument
iota-document = ["dep:identity_iota_core"]
# Enables JSON Proof Token & BBS+ related features
jpt-bbs-plus = ["identity_credential/jpt-bbs-plus", "dep:zkryptium", "dep:bls12_381_plus", "dep:json-proof-token"]
jpt-bbs-plus = [
"identity_credential/jpt-bbs-plus",
"dep:zkryptium",
"dep:bls12_381_plus",
"dep:json-proof-token",
]

[lints]
workspace = true
9 changes: 7 additions & 2 deletions identity_stronghold/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ async-trait = { version = "0.1.64", default-features = false }
bls12_381_plus = { workspace = true, optional = true }
identity_storage = { version = "=1.3.1", path = "../identity_storage", default-features = false }
identity_verification = { version = "=1.3.1", path = "../identity_verification", default-features = false }
iota-crypto = { version = "0.23", default-features = false, features = ["ed25519"] }
iota-crypto = { version = "0.23.2", default-features = false, features = ["ed25519"] }
iota-sdk = { version = "1.1.5", default-features = false, features = ["client", "stronghold"] }
iota_stronghold = { version = "2.1.0", default-features = false }
json-proof-token = { workspace = true, optional = true }
Expand All @@ -38,7 +38,12 @@ zkryptium = { workspace = true }
default = []
# Enables `Send` + `Sync` bounds for the trait implementations on `StrongholdStorage`.
send-sync-storage = ["identity_storage/send-sync-storage"]
bbs-plus = ["identity_storage/jpt-bbs-plus", "dep:zkryptium", "dep:bls12_381_plus", "dep:json-proof-token"]
bbs-plus = [
"identity_storage/jpt-bbs-plus",
"dep:zkryptium",
"dep:bls12_381_plus",
"dep:json-proof-token",
]

[lints]
workspace = true

0 comments on commit f50cbe9

Please sign in to comment.