Skip to content

Conversation

@rodneyosodo
Copy link

@rodneyosodo rodneyosodo commented Jan 16, 2026

What does the PR do?

This PR adds support for encrypted WebAssembly (WASM) workloads by implementing the encrypted WASM media type (application/vnd.wasm.content.layer.v1+wasm+encrypted) and enhancing the keyprovider service with full decryption capabilities. The implementation includes a new cryptographic module supporting AES-256-GCM and AES-256-CTR encryption algorithms, and completes the previously unimplemented UnWrapKey gRPC method that retrieves Key Encryption Keys (KEK) from KBS and performs layer key unwrapping.

The changes enable pulling encrypted WASM layers from OCI registries with proper stream processing that writes WASM binary modules directly to disk (as module.wasm) rather than unpacking them as tar archives. The image-rs components have been updated to recognize and handle encrypted WASM media types throughout the decryption, decoding, and pulling workflows, with support for SHA-256/SHA-512 digest verification.

Reference

@rodneyosodo rodneyosodo requested a review from a team as a code owner January 16, 2026 15:50
@rodneyosodo rodneyosodo force-pushed the enable-wasm-workloads branch 2 times, most recently from 3c906b0 to 729be3a Compare January 16, 2026 15:52
Copy link
Member

@fitzthum fitzthum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks cool.

Can you expand the commit message a little bit.

Also, are there any testing images available for this? I guess it might be tricky since it is encrypted, but ideally we would have coverage here.

Anyway, I will spin the CI. Welcome

@rodneyosodo
Copy link
Author

Hello @fitzthum

I found out the issue might also be related to https://github.com/containers/skopeo

I have submitted these changes containers/container-libs#596 thereafter I will upstream them to containers/skopeo#2791.

I noticed we are using a specific version of skopeo -> containers/skopeo@f64a376. How would we adopt the new changes?

@Xynnn007
Copy link
Member

How would we adopt the new changes?

Without diving deep into this - skopeo is now only used in image encryption, so is it possible for you to generate a test image with new skopeo, but only decrypt with image-rs? A unit test might help

@fitzthum
Copy link
Member

Yeah as @Xynnn007 mentions, skopeo is not a direct dependency for us. It shows up a few places in the repo because we use it to make test images, but we don't have a particular version requirement.

To make sure that image-rs can unpack an image that corresponds to a particular version of skopeo (and whatever else), it's best to provide an image that we can try unpacking in a unit test.

@rodneyosodo rodneyosodo force-pushed the enable-wasm-workloads branch from 729be3a to 1305c61 Compare January 22, 2026 09:56
@rodneyosodo rodneyosodo changed the title feat(ocicrypt): Add encrypted WASM layer media type support Enable WASM Workloads with Encrypted Layer Support Jan 22, 2026
@rodneyosodo
Copy link
Author

Hello @fitzthum and @Xynnn007

I have updated the PR together with the description these are changes we have done to enable us work with encrypted workloads

For example

  • Un encrypted docker.io/rodneydav/wasm-addition:latest
  • Encrypted docker.io/rodneydav/wasm-addition:encrypted

@rodneyosodo rodneyosodo force-pushed the enable-wasm-workloads branch from 1305c61 to edcb6b9 Compare January 22, 2026 10:05
Copy link
Contributor

@mkulke mkulke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

some documentation would be good, e.g. instructions on how to create an image with encrypted wasm layers.

there are also some semantics that would need to be explained (e.g. scheme.starts_with(".provider")) if those are newly introduced it would be good to provide a rationale in the PR description and cover the new behaviour in unit tests

This crate is a port of the ocicrypt golang project, is there similar logic/prior art in the golang ocicrypt library for encrypted wasm layer. We probably want to keep close to that.

Comment on lines 122 to 128
match tokio::io::copy(&mut hash_reader, &mut wasm_file).await {
Ok(_) => Ok(hash_reader.hasher.digest_finalize()),
Err(e) => {
tokio::fs::remove_dir_all(destination).await.ok();
Err(StreamError::FailedToRollBack { source: e })
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
match tokio::io::copy(&mut hash_reader, &mut wasm_file).await {
Ok(_) => Ok(hash_reader.hasher.digest_finalize()),
Err(e) => {
tokio::fs::remove_dir_all(destination).await.ok();
Err(StreamError::FailedToRollBack { source: e })
}
}
let Ok(_) = tokio::io::copy(&mut hash_reader, &mut wasm_file).await else {
tokio::fs::remove_dir_all(destination).await.ok();
return Err(StreamError::FailedToRollBack { source: e });
}
Ok(hash_reader.hasher.digest_finalize())

Comment on lines +36 to +43
// If the key is not 32 bytes (256-bit AES key), try base64 decoding
// Some KBS implementations return base64-encoded keys or text with newlines
if key.len() != 32 {
// First, try to interpret as UTF-8 string and trim whitespace
let key_str = String::from_utf8_lossy(&key);
let trimmed = key_str.trim();
let engine = base64::engine::general_purpose::STANDARD;
let decoded = engine.decode(trimmed.as_bytes())?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this kind of ambiguity is suprising. which KBS implementations are we talking about? do we perform similar heuristics for other layer decryptions?

@rodneyosodo rodneyosodo force-pushed the enable-wasm-workloads branch from edcb6b9 to ad9c6ab Compare January 23, 2026 13:28
@rodneyosodo
Copy link
Author

Hello @mkulke

This crate is a port of the ocicrypt golang project, is there similar logic/prior art in the golang ocicrypt library for encrypted wasm layer. We probably want to keep close to that.

I have submitted this PR containers/ocicrypt#126 with respect to this

- Modified set_perms_ownerships() to skip ownership changes when not root
- Added graceful handling for mknod() and xattr operations requiring privileges
- Updated test_unpack to conditionally check ownership based on root status
- Added is_root() helper and runtime checks for integration tests
- Fixed async_handle_layer to properly set decoder field in LayerMeta
- Updated test_async_handle_layer to reflect current empty diff_id behavior
- All 72 tests now pass without requiring sudo or ignore flags

Signed-off-by: Rodney Osodo <[email protected]>
@rodneyosodo rodneyosodo force-pushed the enable-wasm-workloads branch from f1c6062 to 33c412c Compare January 27, 2026 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants