package secp256k1 import ( "strings" "testing" ) func TestBech32EncodeBasic(t *testing.T) { data := []byte{0x00, 0x01, 0x02} encoded, err := Bech32Encode("test", data) if err != nil { t.Fatalf("encoding failed: %v", err) } // Should start with hrp + "1" if !strings.HasPrefix(encoded, "test1") { t.Errorf("encoded should start with 'test1', got %s", encoded) } } func TestBech32RoundTrip(t *testing.T) { data := []byte{0xde, 0xad, 0xbe, 0xef} encoded, err := Bech32Encode("test", data) if err != nil { t.Fatalf("encoding failed: %v", err) } hrp, decoded, err := Bech32Decode(encoded) if err != nil { t.Fatalf("decoding failed: %v", err) } if hrp != "test" { t.Errorf("hrp mismatch: got %s, want test", hrp) } if len(decoded) != len(data) { t.Fatalf("length mismatch: got %d, want %d", len(decoded), len(data)) } for i := range data { if decoded[i] != data[i] { t.Errorf("byte %d mismatch: got %x, want %x", i, decoded[i], data[i]) } } } func TestBech32DecodeInvalidChecksum(t *testing.T) { // Valid encoding, then corrupt it data := []byte{0x01, 0x02, 0x03} encoded, _ := Bech32Encode("test", data) // Corrupt last character corrupted := encoded[:len(encoded)-1] + "q" _, _, err := Bech32Decode(corrupted) if err == nil { t.Error("should reject invalid checksum") } } func TestBech32DecodeInvalidCharacter(t *testing.T) { _, _, err := Bech32Decode("test1invalid!") if err == nil { t.Error("should reject invalid character") } } func TestNsecEncode(t *testing.T) { priv, _ := NewPrivateKeyFromHex("0000000000000000000000000000000000000000000000000000000000000001") nsec := priv.Nsec() if !strings.HasPrefix(nsec, "nsec1") { t.Errorf("nsec should start with 'nsec1', got %s", nsec) } } func TestNpubEncode(t *testing.T) { priv, _ := NewPrivateKeyFromHex("0000000000000000000000000000000000000000000000000000000000000001") pub := priv.PublicKey() npub := pub.Npub() if !strings.HasPrefix(npub, "npub1") { t.Errorf("npub should start with 'npub1', got %s", npub) } } func TestNsecRoundTrip(t *testing.T) { priv1, _ := GeneratePrivateKey() nsec := priv1.Nsec() priv2, err := PrivateKeyFromNsec(nsec) if err != nil { t.Fatalf("failed to parse nsec: %v", err) } if priv1.D.Cmp(priv2.D) != 0 { t.Error("private key should survive nsec round-trip") } } func TestNpubRoundTrip(t *testing.T) { priv, _ := GeneratePrivateKey() pub1 := priv.PublicKey() npub := pub1.Npub() pub2, err := PublicKeyFromNpub(npub) if err != nil { t.Fatalf("failed to parse npub: %v", err) } // X coordinates should match (y might differ in sign) if pub1.Point.x.value.Cmp(pub2.Point.x.value) != 0 { t.Error("public key x should survive npub round-trip") } } func TestPrivateKeyFromNsecInvalid(t *testing.T) { // Wrong prefix _, err := PrivateKeyFromNsec("npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xjaeh") if err == nil { t.Error("should reject npub as nsec") } } func TestPublicKeyFromNpubInvalid(t *testing.T) { // Wrong prefix _, err := PublicKeyFromNpub("nsec1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0dcpx3") if err == nil { t.Error("should reject nsec as npub") } } // Test with known private key func TestKnownNostrKeyPair(t *testing.T) { // Private key = 1, should give G as public key priv, _ := NewPrivateKeyFromHex("0000000000000000000000000000000000000000000000000000000000000001") nsec := priv.Nsec() // Verify it starts with nsec and round-trips if nsec[:5] != "nsec1" { t.Errorf("nsec should start with nsec1, got %s", nsec) } // Parse it back priv2, err := PrivateKeyFromNsec(nsec) if err != nil { t.Fatalf("failed to parse nsec: %v", err) } if priv.D.Cmp(priv2.D) != 0 { t.Error("nsec round-trip failed") } // Public key should be G pub := priv.PublicKey() npub := pub.Npub() if npub[:5] != "npub1" { t.Errorf("npub should start with npub1, got %s", npub) } // Parse it back and verify x matches G pub2, err := PublicKeyFromNpub(npub) if err != nil { t.Fatalf("failed to parse npub: %v", err) } if pub2.Point.x.value.Cmp(Gx) != 0 { t.Error("npub should decode to G.x") } } func TestSignAndVerifyWithNostrKeys(t *testing.T) { // Create keys priv, _ := GeneratePrivateKey() nsec := priv.Nsec() npub := priv.PublicKey().Npub() // Parse them back priv2, _ := PrivateKeyFromNsec(nsec) pub2, _ := PublicKeyFromNpub(npub) // Sign with parsed private key message := []byte("hello nostr") sig, err := Sign(priv2, message) if err != nil { t.Fatalf("signing failed: %v", err) } // Verify with parsed public key if !Verify(pub2, message, sig) { t.Error("signature should verify with parsed keys") } }