mirror of
https://github.com/luxfi/pqsafe.git
synced 2026-10-30 15:21:41 +00:00
One and only one X-Wing implementation in the Lux stack: zwing. Removed pqsafe/pkg/xwing and pqsafe/pkg/identity; replaced their call sites in capsule + envelope with direct zwing imports (zwing.XWingPublicKey / XWingPrivateKey / XWingEncapsulate / XWingDecapsulate, zwing.Identity / IdentityPublic / Sign / Verify). Same bytes that protect a Z-Wing session now protect a PQSAFE file: one X-Wing, one hybrid-sig surface, vetted once. All E2E tests still pass against the zwing-backed Seal/Open path: TestSealOpenRoundTrip full round-trip TestWrongRecipientCannotOpen wrong key fails closed TestCorruptChunkFails chunk SHA mismatch detected TestTamperedManifestFails zwing hybrid sig refuses TestSwapCapsulesFails zwing X-Wing decap fails for wrong key TestExpiredEnvelopeRefused TTL gate at Open time Example program now uses zwing.GenerateIdentity() and the PQSAFE-IL5-HYBRID-v1 envelope rides on top.
108 lines
2.9 KiB
Go
108 lines
2.9 KiB
Go
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// Example program: end-to-end PQSAFE-IL5-HYBRID-v1 round-trip using
|
|
// luxfi/zwing for the canonical X-Wing + hybrid identity primitives.
|
|
//
|
|
// go run ./_examples/basic
|
|
//
|
|
// Generates a sender + two recipients via zwing.GenerateIdentity(),
|
|
// seals a payload to both, has each recipient open the envelope and
|
|
// verify byte-identical recovery of the plaintext, then proves a
|
|
// tampered chunk fails closed.
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/luxfi/zwing"
|
|
|
|
"github.com/luxfi/pqsafe/pkg/envelope"
|
|
)
|
|
|
|
func main() {
|
|
sender, err := zwing.GenerateIdentity()
|
|
must(err)
|
|
alice, err := zwing.GenerateIdentity()
|
|
must(err)
|
|
bob, err := zwing.GenerateIdentity()
|
|
must(err)
|
|
|
|
plaintext := make([]byte, 200_000)
|
|
if _, err := rand.Read(plaintext); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Printf("Sealing %d bytes for 2 recipients (zwing identities)...\n", len(plaintext))
|
|
|
|
sealed, err := envelope.Seal(envelope.SealInput{
|
|
Plaintext: plaintext,
|
|
Sender: sender,
|
|
Recipients: []envelope.Recipient{
|
|
{ID: "alice@mil", Public: alice.Public()},
|
|
{ID: "bob@gov", Public: bob.Public()},
|
|
},
|
|
PolicyLabel: "CUI",
|
|
PolicyURI: "policy://safe.apps.mil/policies/CUI-IL5-HYBRID-PQ-v1",
|
|
TTL: 24 * time.Hour,
|
|
})
|
|
must(err)
|
|
|
|
fmt.Printf(" manifest: %d bytes\n", len(sealed.ManifestBytes))
|
|
fmt.Printf(" manifest sig: %d bytes (zwing hybrid Ed25519+ML-DSA-65)\n", len(sealed.ManifestSig))
|
|
fmt.Printf(" chunks: %d\n", len(sealed.Chunks))
|
|
fmt.Printf(" capsules: %d\n", len(sealed.Capsules))
|
|
fmt.Printf(" envelope_id: %x...\n", sealed.EnvelopeID[:12])
|
|
|
|
for _, r := range []struct {
|
|
name string
|
|
id string
|
|
sk *zwing.Identity
|
|
}{
|
|
{"Alice", "alice@mil", alice},
|
|
{"Bob", "bob@gov", bob},
|
|
} {
|
|
fmt.Printf("\nOpening as %s...\n", r.name)
|
|
got, err := envelope.Open(envelope.OpenInput{
|
|
ManifestBytes: sealed.ManifestBytes,
|
|
ManifestSig: sealed.ManifestSig,
|
|
Chunks: sealed.Chunks,
|
|
Capsules: sealed.Capsules,
|
|
Recipient: r.sk,
|
|
RecipientID: r.id,
|
|
Now: time.Now(),
|
|
})
|
|
must(err)
|
|
if !bytes.Equal(got, plaintext) {
|
|
log.Fatalf("%s: plaintext mismatch", r.name)
|
|
}
|
|
fmt.Printf(" ✓ recovered %d bytes byte-identical\n", len(got))
|
|
}
|
|
|
|
fmt.Println("\nTampering with chunk 0...")
|
|
sealed.Chunks[0][0] ^= 0xFF
|
|
_, err = envelope.Open(envelope.OpenInput{
|
|
ManifestBytes: sealed.ManifestBytes,
|
|
ManifestSig: sealed.ManifestSig,
|
|
Chunks: sealed.Chunks,
|
|
Capsules: sealed.Capsules,
|
|
Recipient: alice,
|
|
RecipientID: "alice@mil",
|
|
})
|
|
if err == nil {
|
|
log.Fatal("expected Open to fail on tampered chunk")
|
|
}
|
|
fmt.Printf(" ✓ Open refused: %v\n", err)
|
|
fmt.Println("\nE2E PQSAFE-IL5-HYBRID-v1 (via luxfi/zwing) round-trip OK.")
|
|
}
|
|
|
|
func must(err error) {
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|