Skip to content

Commit d544593

Browse files
committed
Create noble-secp256k1.
0 parents  commit d544593

9 files changed

+938
-0
lines changed

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2019 Paul Miller (https://paulmillr.com)
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the “Software”), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# noble-secp256k1
2+
> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.
3+
4+
Noble [secp256k1](https://en.bitcoin.it/wiki/Secp256k1), an elliptic curve that could be used for assymetric encryption and ECDSA signature scheme.
5+
6+
- No dependencies, one small file
7+
- Easily auditable TypeScript/JS code
8+
- Uses es2019 bigint. Supported in Chrome, Firefox, node 10+
9+
10+
## Usage
11+
12+
```js
13+
import * as secp256k1 from "noble-secp256k1";
14+
15+
// You can also pass BigInt:
16+
// const PRIVATE_KEY = 0xa665a45920422f9d417e4867efn;
17+
const PRIVATE_KEY = Uint8Array.from([
18+
0xa6, 0x65, 0xa4, 0x59, 0x20, 0x42, 0x2f,
19+
0x9d, 0x41, 0x7e, 0x48, 0x67, 0xef
20+
]);
21+
const MESSAGE_HASH = "9c1185a5c5e9fc54612808977ee8f548b2258d31";
22+
23+
const publicKey = secp256k1.getPublicKey(PRIVATE_KEY);
24+
const signature = secp256k1.sign(MESSAGE_HASH, PRIVATE_KEY);
25+
const isMessageSigned = secp256k1.verify(signature, MESSAGE_HASH, publicKey);
26+
```
27+
28+
## API
29+
30+
```typescript
31+
function getPublicKey(privateKey: Uint8Array, isCompressed?: false): Uint8Array;
32+
function getPublicKey(privateKey: string, isCompressed?: false): string;
33+
function getPublicKey(privateKey: bigint): Point;
34+
```
35+
`privateKey` will be used to generate public key.
36+
Public key is generated by doing scalar multiplication of a base Point(x, y) by a fixed
37+
integer. The result is another `Point(x, y)` which we will by default encode to hex Uint8Array.
38+
`isCompressed` (default is `false`) determines whether the output should contain `y` coordinate of the point.
39+
40+
```typescript
41+
function sign(hash: Uint8Array, privateKey: Uint8Array | bigint, k?: bigint): Uint8Array;
42+
function sign(hash: string, privateKey: string | bigint, k?: bigint): string;
43+
```
44+
- `hash: Uint8Array | string` - message hash which would be signed
45+
- `privateKey: Uint8Array | string | bigint` - private key which will sign the hash
46+
- `k?: bigint` - *optional* random seed. Default is one from `crypto.getRandomValues()`. **Must be cryptographically secure**, which means `Math.random()` won't work.
47+
- Returns DER encoded ECDSA signature, as hex uint8a / string.
48+
49+
```typescript
50+
function verify(signature: Uint8Array | string | SignResult, hash: Uint8Array | string): boolean
51+
```
52+
- `signature: Uint8Array` - object returned by the `sign` function
53+
- `hash: string | Uint8Array` - message hash that needs to be verified
54+
- `publicKey: string | Point` - e.g. that was generated from `privateKey` by `getPublicKey`
55+
- Returns `boolean`: `true` if `signature == hash`; otherwise `false`
56+
57+
The library also exports helpers:
58+
59+
```typescript
60+
// Finite field over prime Fp
61+
secp256k1.P // 2 ^ 256 - 2 ^ 32 - 977
62+
63+
// Prime order
64+
secp256k1.PRIME_ORDER // 2 ^ 256 - 432420386565659656852420866394968145599
65+
66+
// Base point
67+
secp256k1.BASE_POINT // new secp256k1.Point(x, y) where
68+
// x = 55066263022277343669578718895168534326250603453777594175500187360389116729240n
69+
// y = 32670510020758816978083085130507043184471273380659243275938904335757337482424n;
70+
71+
// Elliptic curve point
72+
secp256k1.Point {
73+
constructor(x: bigint, y: bigint);
74+
// Compressed elliptic curve point representation
75+
static fromHex(hex: Uint8Array | string);
76+
static fromCompressedHex(hex: string);
77+
toHex(): string;
78+
toCompressedHex(): string;
79+
}
80+
secp256k1.SignResult {
81+
constructor(r: bigint, s: bigint);
82+
// DER encoded ECDSA signature
83+
static fromHex(hex: Uint8Array | string);
84+
toHex()
85+
}
86+
```
87+
88+
## License
89+
90+
MIT (c) Paul Miller (https://paulmillr.com), see LICENSE file.

generate-precomputes.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Optional file that allows to generate precomputes
2+
// Not included in NPM distribution to simplify code.
3+
// Precomputes are initially computed powers of two (2^120, 2^121 etc)
4+
// Which are used to speed-up calculations of elliptic curve cryptography.
5+
const fs = require("fs");
6+
const path = require("path");
7+
const { GG, multiple } = require("./index");
8+
9+
let precomputeContent = `import { Point } from "./point";
10+
export default [`
11+
12+
for (let i = 0; i < 257; i++) {
13+
const multiplier = 2n ** BigInt(i);
14+
const result = multiple(GG, multiplier);
15+
precomputeContent = `${precomputeContent}
16+
new Point(
17+
${result.x}n,
18+
${result.y}n,
19+
),`
20+
}
21+
22+
precomputeContent += "\n];";
23+
24+
fs.writeFileSync(path.join(__dirname, "./precomputed.ts"), precomputeContent);

index.d.ts

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*! noble-secp256k1 - MIT License (c) Paul Miller (paulmillr.com) */
2+
export declare const P: bigint;
3+
export declare const PRIME_ORDER: bigint;
4+
declare type PrivKey = Uint8Array | string | bigint | number;
5+
declare type PubKey = Uint8Array | string | Point;
6+
declare type Hex = Uint8Array | string;
7+
declare type Signature = Uint8Array | string | SignResult;
8+
export declare class Point {
9+
x: bigint;
10+
y: bigint;
11+
constructor(x: bigint, y: bigint);
12+
private static fromCompressedHex;
13+
private static fromUncompressedHex;
14+
static fromHex(hash: Hex): Point;
15+
private uncompressedHex;
16+
private compressedHex;
17+
toRawBytes(isCompressed?: boolean): Uint8Array;
18+
toHex(isCompressed?: boolean): string;
19+
}
20+
export declare class SignResult {
21+
r: bigint;
22+
s: bigint;
23+
constructor(r: bigint, s: bigint);
24+
static fromHex(hex: Hex): SignResult;
25+
toHex(): string;
26+
}
27+
export declare const BASE_POINT: Point;
28+
export declare function getPublicKey(privateKey: Uint8Array, isCompressed?: boolean): Uint8Array;
29+
export declare function getPublicKey(privateKey: string, isCompressed?: boolean): string;
30+
export declare function getPublicKey(privateKey: bigint | number, isCompressed?: boolean): Point;
31+
export declare function sign(hash: Uint8Array, privateKey: PrivKey, k?: bigint | number): Uint8Array;
32+
export declare function sign(hash: string, privateKey: PrivKey, k?: bigint | number): string;
33+
export declare function verify(signature: Signature, hash: Hex, publicKey: PubKey): boolean;
34+
export {};

0 commit comments

Comments
 (0)