Skip to content

New feature: SerializableState#48

Draft
ounsworth wants to merge 6 commits into
bcgit:release/0.1.2alphafrom
ounsworth:feature/serialize_state
Draft

New feature: SerializableState#48
ounsworth wants to merge 6 commits into
bcgit:release/0.1.2alphafrom
ounsworth:feature/serialize_state

Conversation

@ounsworth

@ounsworth ounsworth commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Closes #24

This was a feature requested by Simo to be able to pause an operation -- particularly in the middle of a do_update() ... do_update() ... do_final() flow -- stick the serialized crypto operation into a cache, and then resume it later. This is an important feature for implementing TLS loadbalancers that want to be able to cache out the HKDF state and resume it from a different box when the next flight of TCP messages come in.

The only "creative" thing I've added here is that all serialized states are prefixed with a 3-byte semantic version of the library and it's checked on load back in. The idea is that if we ever need to change the serialization of some object, then we can add a guard to refuse to load a serialized object from before the guard (or keep both versions of the deserializer and switch based on the version tag, or whatever ... #futureProofing).

@ounsworth

ounsworth commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

For now, I have added the trait and impl'd it for SHA2.

I'll pause here and give a chance for people to give feedback before I continue with doing the same for:

  • SHA3
  • HMAC
  • HKDF
  • ML-DSA

Comment thread crypto/core/src/serializable_state.rs Outdated
Comment thread crypto/sha2/src/sha256.rs
// insert the version tag
let out: &mut [u8; 105] = add_lib_ver(&mut out_to_return).try_into().unwrap();

// state.h: [u32; 8]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What is state.h?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The internal state of SHA2. It is called H^i_j in FIPS 180-4, see sections 2.2 and 6.2.

Comment thread crypto/sha2/src/sha256.rs
out[40..104].copy_from_slice(&self.x_buf);

// x_buf_off: usize
// in general, a usize should be serialized into a u64, but in this case, it can't ever be larger than 64

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

However, usize can be u32 on 32-bit platforms.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's true, but I don't think it affects the comment, right? For example, serde encodes a usize into a u64 because that's the largest it can ever be on any supported architecture. I think. Encoding a u32 into a u64 is perfectly fine.

I'm not sure I understand the point of your comment.

Comment thread crypto/sha2/src/sha256.rs

impl<PARAMS: SHA2Params> SerializableState<108> for SHA256Internal<PARAMS> {
fn serialize_state(&self) -> [u8; 108] {
let mut out_to_return = [0u8; 108];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Where 108 and other sizes coming from?

Comment thread crypto/sha2/Cargo.toml Outdated
@dghgit

dghgit commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

It looks okay, it'll really help with SLH-DSA as storing intermediate state is almost a requirement to getting the algorithm to work in real time... two things, and you may have to pardon my rust if I've got this wrong. It looks like the version check is automatically rejecting anything older, shouldn't that be newer? Ideally you'd be compatible 1 or 2 versions older, newer might be a bit problematic as you might not know the format. Also, for what it's worth, the LLM suggested LIB_VERSION could be derived from env!("CARGO_PKG_VERSION") with the actual version been something taken from the core API crate.

@ounsworth

Copy link
Copy Markdown
Contributor Author

It looks like the version check is automatically rejecting anything older, shouldn't that be newer?

My idea was to have a framework to be able to carry multiple versions of the parser in case we ... I don't know ... add a boolean flag to one of the objects for some reason.

I honestly hadn't thought about blocking future versions. That's a good idea!

Also, for what it's worth, the LLM suggested LIB_VERSION could be derived from env!("CARGO_PKG_VERSION").

I also did some research but didn't find anything useful. Let me give this a bit more poking. Thanks David!

@ounsworth ounsworth force-pushed the feature/serialize_state branch from 2386f22 to 54f93f6 Compare July 6, 2026 04:00
@ounsworth

Copy link
Copy Markdown
Contributor Author

I don't know why 2d0b7f3 got included in this PR. I also don't know how to remove it. Sorry.

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