Converted keys module.
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
import { test } from "vitest";
|
||||||
|
test("placeholder", () => {});
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import { test } from "vitest";
|
||||||
|
test("placeholder", () => {});
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import { test } from "vitest";
|
||||||
|
test("placeholder", () => {});
|
||||||
|
|||||||
@@ -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");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
34
src/keys.ts
34
src/keys.ts
@@ -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,
|
||||||
|
};
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import { test } from "vitest";
|
||||||
|
test("placeholder", () => {});
|
||||||
|
|||||||
8
src/util.test.ts
Normal file
8
src/util.test.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { test } from "vitest";
|
||||||
|
|
||||||
|
export const testSK =
|
||||||
|
"f43a0435f69529f310bbd1d6263d2fbf0977f54bfe2310cc37ae5904b83bb167";
|
||||||
|
export const testPK =
|
||||||
|
"cfa87f35acbde29ba1ab3ee42de527b2cad33ac487e80cf2d6405ea0042c8fef";
|
||||||
|
|
||||||
|
test("placeholder", () => {});
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import { test } from "vitest";
|
||||||
|
test("placeholder", () => {});
|
||||||
|
|||||||
Reference in New Issue
Block a user