Skip to content

Commit

Permalink
chore: Move WASM WindowOrWorker util into c2pa-crypto (#690)
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten-adobe authored Nov 20, 2024
1 parent 707e56d commit d265026
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 23 deletions.
1 change: 1 addition & 0 deletions internal/crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ web-time = "1.1"

[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies]
getrandom = { version = "0.2.7", features = ["js"] }
js-sys = "0.3.58"

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.3.31"
1 change: 1 addition & 0 deletions internal/crypto/src/tests/webcrypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
// each license.

mod validators;
mod window_or_worker;
21 changes: 21 additions & 0 deletions internal/crypto/src/tests/webcrypto/window_or_worker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2024 Adobe. All rights reserved.
// This file is licensed to you under the Apache License,
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
// or the MIT license (http://opensource.org/licenses/MIT),
// at your option.

// Unless required by applicable law or agreed to in writing,
// this software is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
// specific language governing permissions and limitations under
// each license.

use wasm_bindgen_test::wasm_bindgen_test;

use crate::webcrypto::WindowOrWorker;

#[wasm_bindgen_test]
fn has_crypto_library() {
WindowOrWorker::new().unwrap().crypto().unwrap();
}
3 changes: 3 additions & 0 deletions internal/crypto/src/webcrypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@
//! [`SubtleCrypto`]: https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.SubtleCrypto.html

pub mod validators;

mod window_or_worker;
pub use window_or_worker::{WasmCryptoError, WindowOrWorker};
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,28 @@
// specific language governing permissions and limitations under
// each license.

#![allow(missing_docs)]

use thiserror::Error;
use wasm_bindgen::{prelude::*, JsCast, JsValue};
use web_sys::{Crypto, SubtleCrypto, Window, WorkerGlobalScope};

use crate::{Error, Result};

// Adapted from gloo's implementation, since there doesn't seem to be a great way to do context checking using
// wasm-bindgen/web-sys without using something like `js_sys::eval`. References:
// - Issue: https://github.com/rustwasm/wasm-bindgen/issues/1046
// - Issue: https://github.com/rustwasm/wasm-bindgen/issues/2148#issuecomment-638606446
// - Code reference: https://git.io/J9crn

/// Adapted from gloo's implementation, since there doesn't seem to be a great
/// way to do context checking using `wasm-bindgen/web-sys` without using
/// something like `js_sys::eval`.
///
/// References:
///
/// - Issue: https://github.com/rustwasm/wasm-bindgen/issues/1046
/// - Issue: https://github.com/rustwasm/wasm-bindgen/issues/2148#issuecomment-638606446
/// - Code reference: https://git.io/J9crn
pub enum WindowOrWorker {
Window(Window),
Worker(WorkerGlobalScope),
}

impl WindowOrWorker {
pub fn new() -> Result<Self> {
pub fn new() -> Result<Self, WasmCryptoError> {
#[wasm_bindgen]
extern "C" {
type Global;
Expand All @@ -47,21 +51,31 @@ impl WindowOrWorker {
} else if !global.worker().is_undefined() {
Ok(Self::Worker(global.unchecked_into()))
} else {
Err(Error::WasmInvalidContext)
Err(WasmCryptoError::UnknownContext)
}
}

pub fn crypto(&self) -> Result<Crypto> {
pub fn crypto(&self) -> Result<Crypto, WasmCryptoError> {
match self {
Self::Window(window) => window.crypto(),
Self::Worker(worker) => worker.crypto(),
}
.map_err(|_err| Error::WasmNoCrypto)
.map_err(|_err| WasmCryptoError::NoCryptoAvailable)
}

pub fn subtle_crypto(&self) -> Result<SubtleCrypto> {
let crypto = self.crypto()?;

Ok(crypto.subtle())
pub fn subtle_crypto(&self) -> Result<SubtleCrypto, WasmCryptoError> {
Ok(self.crypto()?.subtle())
}
}

/// Error returned when cryptography libraries are unavailable.
#[derive(Debug, Error, Eq, PartialEq)]
pub enum WasmCryptoError {
/// Unknown context.
#[error("could not find window or worker in global environment")]
UnknownContext,

/// Crypto library unavailable.
#[error("window or worker's .crypto() method failed")]
NoCryptoAvailable,
}
10 changes: 10 additions & 0 deletions sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,13 @@ impl From<c2pa_crypto::openssl::OpenSslMutexUnavailable> for Error {
Self::OpenSslMutexError
}
}

#[cfg(target_arch = "wasm32")]
impl From<c2pa_crypto::webcrypto::WasmCryptoError> for Error {
fn from(err: c2pa_crypto::webcrypto::WasmCryptoError) -> Self {
match err {
c2pa_crypto::webcrypto::WasmCryptoError::UnknownContext => Self::WasmInvalidContext,
c2pa_crypto::webcrypto::WasmCryptoError::NoCryptoAvailable => Self::WasmNoCrypto,
}
}
}
3 changes: 1 addition & 2 deletions sdk/src/utils/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,11 +496,10 @@ impl crate::signer::AsyncSigner for WebCryptoSigner {
}

async fn sign(&self, claim_bytes: Vec<u8>) -> crate::error::Result<Vec<u8>> {
use c2pa_crypto::webcrypto::WindowOrWorker;
use js_sys::{Array, Object, Reflect, Uint8Array};
use wasm_bindgen_futures::JsFuture;
use web_sys::CryptoKey;

use crate::wasm::context::WindowOrWorker;
let context = WindowOrWorker::new().unwrap();
let crypto = context.subtle_crypto().unwrap();

Expand Down
2 changes: 0 additions & 2 deletions sdk/src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
// specific language governing permissions and limitations under
// each license.

#[cfg(target_arch = "wasm32")]
pub(crate) mod context;
#[cfg(target_arch = "wasm32")]
pub(crate) mod rsa_wasm_signer;
#[cfg(target_arch = "wasm32")]
Expand Down
3 changes: 2 additions & 1 deletion sdk/src/wasm/util.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use c2pa_crypto::webcrypto::WindowOrWorker;
use web_sys::Crypto;

use crate::{wasm::context::WindowOrWorker, Error, Result};
use crate::{Error, Result};

pub fn get_random_values(len: usize) -> Result<Vec<u8>> {
let context = WindowOrWorker::new();
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/wasm/webcrypto_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@

use std::convert::TryFrom;

use c2pa_crypto::SigningAlg;
use c2pa_crypto::{webcrypto::WindowOrWorker, SigningAlg};
use js_sys::{Array, ArrayBuffer, Object, Reflect, Uint8Array};
use spki::SubjectPublicKeyInfoRef;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::JsFuture;
use web_sys::{CryptoKey, SubtleCrypto};
use x509_parser::der_parser::ber::{parse_ber_sequence, BerObject};

use crate::{wasm::context::WindowOrWorker, Error, Result};
use crate::{Error, Result};

pub struct EcKeyImportParams {
name: String,
Expand Down

0 comments on commit d265026

Please sign in to comment.