Converted keys module.

This commit is contained in:
Jay
2025-10-24 10:09:57 -04:00
parent 7f2e872e5b
commit 60a5c86b2b
8 changed files with 98 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
import { test } from "vitest";
test("placeholder", () => {});

View File

@@ -0,0 +1,2 @@
import { test } from "vitest";
test("placeholder", () => {});

View File

@@ -0,0 +1,2 @@
import { test } from "vitest";
test("placeholder", () => {});

View File

@@ -0,0 +1,46 @@
import { describe, test, expect } from "vitest";
import { Keys } from "./keys";
import { HEX_64_PATTERN } from "./constants";
import { testSK, testPK } from "./util.test";
describe("Keys.generatePrivate", () => {
test("returns 64 hex characters", () => {
const privateKey = Keys.generatePrivate();
expect(privateKey).toMatch(HEX_64_PATTERN);
});
test("generates unique keys", () => {
const key1 = Keys.generatePrivate();
const key2 = Keys.generatePrivate();
expect(key1).not.toBe(key2);
});
});
describe("Keys.getPublic", () => {
test("derives correct public key", () => {
const publicKey = Keys.getPublic(testSK);
expect(publicKey).toBe(testPK);
});
test("throws on invalid private key - too short", () => {
expect(() => Keys.getPublic("abc123")).toThrow(
"private key must be 64 lowercase hex characters",
);
});
test("throws on invalid private key - non-hex", () => {
expect(() =>
Keys.getPublic(
"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
),
).toThrow("private key must be 64 lowercase hex characters");
});
test("throws on invalid private key - uppercase", () => {
expect(() =>
Keys.getPublic(
"F43A0435F69529F310BBD1D6263D2FBF0977F54BFE2310CC37AE5904B83BB167",
),
).toThrow("private key must be 64 lowercase hex characters");
});
});

View File

@@ -0,0 +1,34 @@
import { schnorr } from "@noble/secp256k1";
import { HEX_64_PATTERN } from "./constants";
import { MalformedPrivKeyError } from "./errors";
/**
* Generates a new random secp256k1 private key.
* @returns 64-character lowercase hexadecimal string
*/
function generatePrivate(): string {
const { secretKey } = schnorr.keygen();
return Buffer.from(secretKey).toString("hex");
}
/**
* Derives the public key from a private key hex string.
* @param privateKey - 64-character lowercase hexadecimal private key
* @returns 64-character lowercase hexadecimal public key (x-coordinate only)
* @throws {MalformedPrivKeyError} If private key is not 64 lowercase hex characters
*/
function getPublic(privateKey: string): string {
if (!HEX_64_PATTERN.test(privateKey)) {
throw new MalformedPrivKeyError();
}
const privateKeyBytes = Buffer.from(privateKey, "hex");
const publicKeyBytes = schnorr.getPublicKey(privateKeyBytes);
return Buffer.from(publicKeyBytes).toString("hex");
}
export const Keys = {
generatePrivate,
getPublic,
};

View File

@@ -0,0 +1,2 @@
import { test } from "vitest";
test("placeholder", () => {});

8
src/util.test.ts Normal file
View File

@@ -0,0 +1,8 @@
import { test } from "vitest";
export const testSK =
"f43a0435f69529f310bbd1d6263d2fbf0977f54bfe2310cc37ae5904b83bb167";
export const testPK =
"cfa87f35acbde29ba1ab3ee42de527b2cad33ac487e80cf2d6405ea0042c8fef";
test("placeholder", () => {});

View File

@@ -0,0 +1,2 @@
import { test } from "vitest";
test("placeholder", () => {});