Files
zeekay a46eba450e pqrns: decomplect — consume luxfi/zwing for hybrid identity
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.
2026-05-12 20:34:47 -07:00

62 lines
1.7 KiB
Go

// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package identity_test
import (
"bytes"
"testing"
"github.com/luxfi/zwing"
"github.com/luxfi/pqrns/pkg/identity"
)
func TestSignAndVerifyHybrid(t *testing.T) {
sk, err := zwing.GenerateIdentity()
if err != nil {
t.Fatalf("zwing.GenerateIdentity: %v", err)
}
digest := []byte("test-digest-bytes")
sig := sk.Sign([]byte(identity.CtxIdentitySig), digest)
if err := sk.Public().Verify([]byte(identity.CtxIdentitySig), digest, sig); err != nil {
t.Fatalf("Verify (correct): %v", err)
}
// Wrong context refuses to verify.
if err := sk.Public().Verify([]byte(identity.CtxLinkKDF), digest, sig); err == nil {
t.Fatal("Verify with wrong context should fail")
}
// Tampered digest refuses to verify.
tampered := append([]byte(nil), digest...)
tampered[0] ^= 0x01
if err := sk.Public().Verify([]byte(identity.CtxIdentitySig), tampered, sig); err == nil {
t.Fatal("Verify with tampered digest should fail")
}
}
func TestFingerprintStable(t *testing.T) {
sk, _ := zwing.GenerateIdentity()
fp1 := identity.Fingerprint(sk.Public())
fp2 := identity.Fingerprint(sk.Public())
if !bytes.Equal(fp1[:], fp2[:]) {
t.Fatalf("fingerprint not stable: %x vs %x", fp1, fp2)
}
if len(fp1) != identity.FingerprintSize {
t.Fatalf("fingerprint size %d != %d", len(fp1), identity.FingerprintSize)
}
}
func TestFingerprintsDiffer(t *testing.T) {
a, _ := zwing.GenerateIdentity()
b, _ := zwing.GenerateIdentity()
fa := identity.Fingerprint(a.Public())
fb := identity.Fingerprint(b.Public())
if bytes.Equal(fa[:], fb[:]) {
t.Fatal("two fresh identities produced the same fingerprint")
}
}