WizardConnect/packages/core/src/utilnostr.test.ts
2026-03-06 11:38:09 +01:00

104 lines
3.8 KiB
TypeScript

// 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);
});
});
});