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.
62 lines
1.7 KiB
Go
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")
|
|
}
|
|
}
|