Skip to content

Add compressed lamport pubkey fingerprint#78

Open
danielemiliogarcia wants to merge 13 commits intodevfrom
compress-lamport
Open

Add compressed lamport pubkey fingerprint#78
danielemiliogarcia wants to merge 13 commits intodevfrom
compress-lamport

Conversation

@danielemiliogarcia
Copy link
Contributor

@danielemiliogarcia danielemiliogarcia commented Feb 23, 2026

Add compressed lamport pubkey fingerprint

This PR introduces a compressed representation of LamportPublicKey to reduce storage and transmission size, along with a matching expansion API that re-derives or reloads the full key and verifies integrity via BLAKE3.

Motivation

A Lamport public key grows linearly with the message bit length: a key for a 256-bit message already serialises to several kilobytes. Storing or passing the full key around adds unnecessary overhead. This PR addresses that by separating the identity of a key (its BLAKE3 fingerprint + metadata) from its full material.

Example size comparison (from the updated example output):

Form Bytes (1-bit key) Bytes (256-bit key)
Compressed 51 51
Uncompressed 115 20,515

The ratio grows with message_bit_length.


Changes

New type - LamportCompressedPubKey

  • LamportPublicKey::to_compressed() and the From<&LamportPublicKey> impl construct it automatically.
  • verify_against(&LamportPublicKey) checks that a re-derived key still matches the stored fingerprint.

New trait - LamportPubKeyId

Implemented by both LamportPublicKey (computes on the fly) and LamportCompressedPubKey (returns stored id). Used to unify operations.

New function - KeyManager::expand_lamport()

Reconstructs the full LamportPublicKey

  • Derived keys — re-derives from the seed using the embedded derivation index and message bit length.
  • Imported keys — loads the stored private key from the keystore and derives the public key from it.

After reconstruction, the BLAKE3 fingerprint is verified against the stored id

Tests

Unit tests have been added

Comment on lines +143 to +150
println!(
"\nSerialized compressed Lamport public key ({} bytes)",
serialized_compressed.len()
);
println!(
"Serialized uncompressed Lamport public key ({} bytes)",
serialized_uncompressed.len()
);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Serialized compressed Lamport public key (51 bytes)
Serialized uncompressed Lamport public key (20515 bytes)

Comment on lines +32 to +42

// Difference in size between serialized compressed and uncompressed public key
println!(
"\nSerialized compressed Lamport public key ({} bytes)",
bincode::serialize(&lamport_pubkey.to_compressed()).unwrap().len()
);
println!(
"Serialized uncompressed Lamport public key ({} bytes)",
bincode::serialize(&lamport_pubkey).unwrap().len()
);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Even at 1 bit level (as used for garbled circuits wire labels values) the compression reduces the key > 2x

Serialized compressed Lamport public key (51 bytes)
Serialized uncompressed Lamport public key (115 bytes)

@danielemiliogarcia danielemiliogarcia marked this pull request as ready for review February 25, 2026 22: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.

1 participant