Zipsign Signature Verification Fix - Handover Document

Date: 2025-01-15 Author: Terraphim AI Team Issue: Integration test test_signed_archive_verification failing with NoMatch error


Problem Summary

The test_signed_archive_verification integration test was failing even though:

  • zipsign CLI v0.2.0 was correctly signing archives
  • zipsign CLI verification succeeded (zipsign verify tar test.tar.gz public.key returned OK)
  • The correct public key was being provided

Error: Expected Valid, got Invalid { reason: "Signature verification failed: no matching key/signature pair found" }


Root Cause Analysis

Debug Investigation

Created a standalone test program at /tmp/debug_zipsign to test zipsign-api v0.2.0 directly:

// Without context - FAILS
zipsign_api::verify::verify_tar(&mut cursor, &verifying_key, None)
// Result: NoMatch(NoMatch)

// With filename context - SUCCEEDS
zipsign_api::verify::verify_tar(&mut cursor, &verifying_key, Some(filename.as_bytes()))
// Result: Ok(0)

The Issue

zipsign uses the archive filename as a context/salt parameter when computing signatures. The context is:

  • Used during signing: zipsign sign tar archive.tar.gz private.key
  • Defaults to the input filename
  • Required during verification to reproduce the same hash

The original verify_archive_signature() function was calling verify_tar() with None as the context, causing signature mismatch.


The Fix

File: crates/terraphim_update/src/signature.rs

Changes (lines 128-138):

// Before (BROKEN):
match zipsign_api::verify::verify_tar(&mut cursor, &verifying_key, None) {

// After (FIXED):
let context: Option<Vec<u8>> = archive_path
    .file_name()
    .map(|n| n.to_string_lossy().as_bytes().to_vec());

let mut cursor = Cursor::new(archive_bytes);
let context_ref: Option<&[u8]> = context.as_deref();
match zipsign_api::verify::verify_tar(&mut cursor, &verifying_key, context_ref) {

Why This Works

  1. Extract the filename from the archive path using file_name()
  2. Convert to bytes (handling Unicode correctly with to_string_lossy())
  3. Store in a Vec<u8> to ensure lifetime validity
  4. Pass as Option<&[u8]> to verify_tar()

Test Results

All Signature Tests Pass

running 1 test
zipsign CLI version: zipsign 0.2.0
test integration_tests::test_signed_archive_verification ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 measured; 14 filtered out

Full Test Suite

  • 15 signature tests passed
  • 28 doc tests passed
  • Build succeeds
  • Clippy clean (only unrelated warning)

Related Files

  1. Main fix: crates/terraphim_update/src/signature.rs
  2. Integration test: crates/terraphim_update/tests/signature_test.rs
  3. Forked dependency: https://github.com/AlexMikhalev/self_update.git (branch: update-zipsign-api-v0.2)
  4. Debug artifacts: /tmp/debug_zipsign/, /tmp/zipsign_test2/

Version Compatibility

| Component | Version | Notes | |-----------|---------|-------| | zipsign CLI | 0.2.0 | System installed | | zipsign-api | 0.2.0 | crates.io | | self_update (fork) | 0.42.0 | Patched to use zipsign-api 0.2 |


Lessons Learned

  1. Always pass context to verify_tar(): The zipsign documentation indicates context is optional but required when the CLI was used with default settings.

  2. Test with standalone programs: Creating a minimal test outside the test suite helped isolate the issue quickly.

  3. Version compatibility matters: The original issue was also related to zipsign-api v0.1.x vs v0.2.x incompatibility with zipsign CLI v0.2.0.


Commit History

  • 3d75ecf8 - fix(signing): pass context parameter to verify_tar for signature verification
  • 9f613abb - docs(signing): mark Issue #421 complete with security audit passed
  • cc30862a - feat(signing): integrate 1Password for secure key retrieval
  • 93d634d0 - docs(progress): mark Step 9 complete - Ed25519 key pair generated and embedded

Verification Commands

# Run signature tests
cargo test -p terraphim_update --features integration-signing

# Run specific integration test
cargo test -p terraphim_update test_signed_archive_verification --features integration-signing -- --nocapture

# Verify CLI works
zipsign verify tar test.tar.gz public.key

Next Steps

  • [ ] Merge update-zipsign-api-v0.2 branch into main
  • [ ] Update self_update fork PR if upstream is available
  • [ ] Document the context parameter requirement in code comments