// Copyright (C) 2026 Whiterun LLC, // This software is licensed under the GNU Lesser General Public License (LGPL), version 3.0 or later. // A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/lgpl-3.0.html import { describe, it, expect } from "vitest"; import { deriveNostrPublicKey, deriveNostrPublicKeyBytes, } from "./utilnostr.js"; import { generatePrivateKey, hexToBin, binToHex, secp256k1, } from "@bitauth/libauth"; describe("utilnostr", () => { describe("deriveNostrPublicKey", () => { it("should derive a valid Nostr public key from a private key", () => { const privateKey = generatePrivateKey(); const publicKey = deriveNostrPublicKey(privateKey); // Nostr public key should be 64 hex characters (32 bytes) expect(publicKey).toHaveLength(64); expect(/^[0-9a-f]+$/.test(publicKey)).toBe(true); }); it("should produce the same public key for the same private key", () => { const privateKey = generatePrivateKey(); const publicKey1 = deriveNostrPublicKey(privateKey); const publicKey2 = deriveNostrPublicKey(privateKey); expect(publicKey1).toBe(publicKey2); }); it("should produce different public keys for different private keys", () => { const privateKey1 = generatePrivateKey(); const privateKey2 = generatePrivateKey(); const publicKey1 = deriveNostrPublicKey(privateKey1); const publicKey2 = deriveNostrPublicKey(privateKey2); expect(publicKey1).not.toBe(publicKey2); }); it("should handle private key from hex string", () => { const privateKeyHex = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; const privateKey = hexToBin(privateKeyHex); const publicKey = deriveNostrPublicKey(privateKey); expect(publicKey).toHaveLength(64); expect(/^[0-9a-f]+$/.test(publicKey)).toBe(true); }); it("should match the pattern used in key-exchange", () => { const privateKey = generatePrivateKey(); const publicKey = deriveNostrPublicKey(privateKey); // Verify it's the same as the manual pattern const result = secp256k1.derivePublicKeyCompressed(privateKey); if (typeof result === "string") throw new Error(result); const publicKeyNostr = result.slice(1); const publicKeyHex = binToHex(publicKeyNostr); expect(publicKey).toBe(publicKeyHex); }); }); describe("deriveNostrPublicKeyBytes", () => { it("should derive a valid Nostr public key as bytes", () => { const privateKey = generatePrivateKey(); const publicKeyBytes = deriveNostrPublicKeyBytes(privateKey); // Nostr public key should be 32 bytes expect(publicKeyBytes).toHaveLength(32); expect(publicKeyBytes).toBeInstanceOf(Uint8Array); }); it("should match the hex version when converted", () => { const privateKey = generatePrivateKey(); const publicKeyHex = deriveNostrPublicKey(privateKey); const publicKeyBytes = deriveNostrPublicKeyBytes(privateKey); expect(binToHex(publicKeyBytes)).toBe(publicKeyHex); }); it("should produce the same bytes for the same private key", () => { const privateKey = generatePrivateKey(); const publicKeyBytes1 = deriveNostrPublicKeyBytes(privateKey); const publicKeyBytes2 = deriveNostrPublicKeyBytes(privateKey); expect(publicKeyBytes1).toEqual(publicKeyBytes2); }); it("should produce different bytes for different private keys", () => { const privateKey1 = generatePrivateKey(); const privateKey2 = generatePrivateKey(); const publicKeyBytes1 = deriveNostrPublicKeyBytes(privateKey1); const publicKeyBytes2 = deriveNostrPublicKeyBytes(privateKey2); expect(publicKeyBytes1).not.toEqual(publicKeyBytes2); }); }); });