mirror of
https://github.com/luxfi/pqrns.git
synced 2026-10-30 15:21:45 +00:00
pqrns/pkg/identity now owns only the PQ-RNS wire constants (size
totals, IdentityKind enum, fingerprint shape) and the PQ-RNS-specific
domain-separation context strings. Identity keys themselves come from
zwing.Identity / zwing.IdentityPublic — same canonical hybrid
identity used by Z-Wing on TCP/IP. One signing surface for the whole
Lux stack.
Helpers:
identity.Fingerprint(*zwing.IdentityPublic) [16]byte
RNS-shape SHA-256-prefix fingerprint over the
zwing canonical identity-blob bytes.
identity.X25519PubBytes(*zwing.XWingPublicKey) []byte
32-byte X25519 leg for native-RNS addressing.
identity.X25519PubFromBytes(b) (*ecdh.PublicKey, error)
parse a raw X25519 pub.
E2E tests pass:
TestSignAndVerifyHybrid sign + verify via zwing
TestSignAndVerifyHybrid wrong context refuses
TestSignAndVerifyHybrid tampered digest refuses
TestFingerprintStable deterministic
TestFingerprintsDiffer no collision
Example: `go run ./_examples/basic` — generates two zwing identities,
prints fingerprints, signs+verifies under PQRNS-IDENTITY-SIG-v1.
52 lines
1.4 KiB
Go
52 lines
1.4 KiB
Go
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// Example: generate two zwing hybrid identities, exchange announce-
|
|
// style fingerprints, run a hybrid sign/verify pair under the PQ-RNS
|
|
// identity domain-separation context.
|
|
//
|
|
// go run ./_examples/basic
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/luxfi/zwing"
|
|
|
|
"github.com/luxfi/pqrns/pkg/identity"
|
|
)
|
|
|
|
func main() {
|
|
alice, err := zwing.GenerateIdentity()
|
|
must(err)
|
|
bob, err := zwing.GenerateIdentity()
|
|
must(err)
|
|
|
|
fa := identity.Fingerprint(alice.Public())
|
|
fb := identity.Fingerprint(bob.Public())
|
|
fmt.Printf("alice fingerprint: %x\n", fa)
|
|
fmt.Printf("bob fingerprint: %x\n", fb)
|
|
|
|
msg := []byte("hello-from-alice")
|
|
sig := alice.Sign([]byte(identity.CtxIdentitySig), msg)
|
|
fmt.Printf("\nalice signed %d-byte message via zwing hybrid (Ed25519 + ML-DSA-65):\n", len(msg))
|
|
fmt.Printf(" signature blob: %d bytes\n", len(sig))
|
|
|
|
if err := alice.Public().Verify([]byte(identity.CtxIdentitySig), msg, sig); err != nil {
|
|
log.Fatalf("verify (alice's sig): %v", err)
|
|
}
|
|
fmt.Println("✓ bob verified alice's hybrid signature")
|
|
|
|
if err := alice.Public().Verify([]byte(identity.CtxLinkKDF), msg, sig); err == nil {
|
|
log.Fatal("verify with wrong context should have failed")
|
|
}
|
|
fmt.Println("✓ verify with wrong context refused (domain separation enforced)")
|
|
}
|
|
|
|
func must(err error) {
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|