Skip to content

Commit 56c9edf

Browse files
committed
Add functions to create private keys to the secp256k1 module
1 parent deb0844 commit 56c9edf

File tree

5 files changed

+87
-13
lines changed

5 files changed

+87
-13
lines changed

packages/ethereum-cryptography/README.md

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,27 +345,39 @@ The `secp256k1` submodule provides a library for elliptic curve operations on
345345
the curve Secp256k1.
346346

347347
It has the exact same API than the version `4.x` of the [`secp256k1`](https://github.com/cryptocoinjs/secp256k1-node)
348-
module from cryptocoinjs.
348+
module from cryptocoinjs, with two added function to create private keys.
349+
350+
### Creating private keys
351+
352+
Secp256k1 private keys need to be cryptographycally secure random numbers with
353+
certain caracteristics. If this is not the case, the security of Secp256k1 is
354+
compromissed.
355+
356+
We strongly recommend to use this module to create new private keys.
349357

350358
### Function types
351359

352-
Go to [`secp256k1`'s documentation](https://github.com/cryptocoinjs/secp256k1-node)
353-
to learn how to use it.
360+
Functions to create private keys:
361+
362+
```ts
363+
function createPrivateKey(): Promise<Uint8Array>;
364+
365+
function function createPrivateKeySync(): Uint8Array;
366+
```
367+
368+
For the rest of the functions, pleasse read [`secp256k1`'s documentation](https://github.com/cryptocoinjs/secp256k1-node).
354369
355370
### Example usage
356371
357372
```js
358-
const { sign } = require("ethereum-cryptography/secp256k1");
373+
const { sign, createPrivateKeySync } = require("ethereum-cryptography/secp256k1");
359374

360375
const msgHash = Buffer.from(
361376
"82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28",
362377
"hex"
363378
);
364379

365-
const privateKey = Buffer.from(
366-
"3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1",
367-
"hex"
368-
);
380+
const privateKey = createPrivateKeySync();
369381

370382
console.log(Buffer.from(sign(msgHash, privateKey)).signature.toString("hex"));
371383
```
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,24 @@
1+
import { privateKeyVerify } from "secp256k1";
2+
import { getRandomBytes, getRandomBytesSync } from "./random";
3+
4+
const SECP256K1_PRIVATE_KEY_SIZE = 32;
5+
6+
export async function createPrivateKey(): Promise<Uint8Array> {
7+
while (true) {
8+
const pk = await getRandomBytes(SECP256K1_PRIVATE_KEY_SIZE);
9+
if (privateKeyVerify(pk)) {
10+
return pk;
11+
}
12+
}
13+
}
14+
15+
export function createPrivateKeySync(): Uint8Array {
16+
while (true) {
17+
const pk = getRandomBytesSync(SECP256K1_PRIVATE_KEY_SIZE);
18+
if (privateKeyVerify(pk)) {
19+
return pk;
20+
}
21+
}
22+
}
23+
124
export * from "secp256k1";
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
import { ecdsaRecover, ecdsaSign, publicKeyConvert } from "../../src/secp256k1";
1+
import {
2+
createPrivateKey,
3+
createPrivateKeySync,
4+
ecdsaRecover,
5+
ecdsaSign,
6+
privateKeyVerify,
7+
publicKeyConvert
8+
} from "../../src/secp256k1";
29
import { createTests } from "../test-vectors/secp256k1";
310

4-
createTests(ecdsaSign, ecdsaRecover, publicKeyConvert);
11+
createTests(
12+
ecdsaSign,
13+
ecdsaRecover,
14+
publicKeyConvert,
15+
createPrivateKey,
16+
createPrivateKeySync,
17+
privateKeyVerify
18+
);
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
import { ecdsaRecover, ecdsaSign, publicKeyConvert } from "../../src/secp256k1";
1+
import {
2+
createPrivateKey,
3+
createPrivateKeySync,
4+
ecdsaRecover,
5+
ecdsaSign,
6+
privateKeyVerify,
7+
publicKeyConvert
8+
} from "../../src/secp256k1";
29
import { createTests } from "../test-vectors/secp256k1";
310

4-
createTests(ecdsaSign, ecdsaRecover, publicKeyConvert);
11+
createTests(
12+
ecdsaSign,
13+
ecdsaRecover,
14+
publicKeyConvert,
15+
createPrivateKey,
16+
createPrivateKeySync,
17+
privateKeyVerify
18+
);

packages/ethereum-cryptography/test/test-vectors/secp256k1.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,20 @@ export function createTests(
1111
signature: Uint8Array,
1212
compressed?: boolean
1313
) => Uint8Array,
14-
publicKeyConvert: (publicKey: Uint8Array, compressed?: boolean) => Uint8Array
14+
publicKeyConvert: (publicKey: Uint8Array, compressed?: boolean) => Uint8Array,
15+
createPrivakeKey: () => Promise<Uint8Array>,
16+
createPrivakeKeySync: () => Uint8Array,
17+
privateKeyVerify: (pk: Uint8Array) => boolean
1518
) {
1619
describe("secp256k1", function() {
20+
it("should create valid private keys", async function() {
21+
const asyncPk = await createPrivakeKey();
22+
const syncPk = createPrivakeKeySync();
23+
24+
assert.isTrue(privateKeyVerify(asyncPk));
25+
assert.isTrue(privateKeyVerify(syncPk));
26+
});
27+
1728
it("Should sign correctly", function() {
1829
// This test has been adapted from ethereumjs-util
1930
// https://github.com/ethereumjs/ethereumjs-util/blob/3b1085059194b02354177d334f89cd82a5187883/test/index.js#L531

0 commit comments

Comments
 (0)