ed25519-keygen
Advanced tools
Comparing version 0.4.8 to 0.4.10
import { ed25519 } from '@noble/curves/ed25519'; | ||
import { concatBytes } from '@noble/hashes/utils'; | ||
import { hex, base32, utils } from '@scure/base'; | ||
import { concatBytes } from 'micro-packed'; | ||
const base36 = utils.chain(utils.radix(36), utils.alphabet('0123456789abcdefghijklmnopqrstuvwxyz'), utils.padding(0), utils.join('')); | ||
@@ -5,0 +5,0 @@ export function formatPublicKey(pubBytes) { |
{ | ||
"name": "ed25519-keygen", | ||
"version": "0.4.8", | ||
"description": "Generate ed25519 keys for SSH, PGP (GPG), TOR and SLIP-0010 hdkey", | ||
"version": "0.4.10", | ||
"description": "Generate ed25519 keys for SSH, PGP (GPG), TOR, IPNS and SLIP-0010 hdkey", | ||
"type": "module", | ||
@@ -79,2 +79,8 @@ "main": "index.js", | ||
}, | ||
"scripts": { | ||
"build": "tsc", | ||
"lint": "prettier --check src", | ||
"format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'", | ||
"test": "node test/index.js" | ||
}, | ||
"author": "Paul Miller (https://paulmillr.com)", | ||
@@ -100,14 +106,3 @@ "license": "MIT", | ||
], | ||
"funding": [ | ||
{ | ||
"type": "individual", | ||
"url": "https://paulmillr.com/funding/" | ||
} | ||
], | ||
"scripts": { | ||
"build": "tsc", | ||
"lint": "prettier --check src", | ||
"format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'", | ||
"test": "node test/index.js" | ||
} | ||
} | ||
"funding": "https://paulmillr.com/funding/" | ||
} |
33
pgp.js
import { ed25519, x25519 } from '@noble/curves/ed25519'; | ||
import { bytesToNumberBE, equalBytes, numberToHexUnpadded } from '@noble/curves/abstract/utils'; | ||
import { crypto } from '@noble/hashes/crypto'; | ||
import { ripemd160 } from '@noble/hashes/ripemd160'; | ||
import { sha1 } from '@noble/hashes/sha1'; | ||
import { ripemd160 } from '@noble/hashes/ripemd160'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { sha512 } from '@noble/hashes/sha512'; | ||
import { sha3_256 } from '@noble/hashes/sha3'; | ||
import { randomBytes } from '@noble/hashes/utils'; | ||
import { crypto } from '@noble/hashes/crypto'; | ||
import { concatBytes, randomBytes } from '@noble/hashes/utils'; | ||
import { utf8, hex } from '@scure/base'; | ||
import * as P from 'micro-packed'; | ||
import { concatBytes } from 'micro-packed'; | ||
import { utf8, hex } from '@scure/base'; | ||
function numberToHexUnpadded(num) { | ||
let hex = num.toString(16); | ||
hex = hex.length & 1 ? `0${hex}` : hex; | ||
return hex; | ||
} | ||
function bytesToNumber(bytes) { | ||
return BigInt('0x' + hex.encode(bytes)); | ||
} | ||
function equalBytes(a, b) { | ||
if (a.length !== b.length) | ||
return false; | ||
for (let i = 0; i < a.length; i++) { | ||
if (a[i] !== b[i]) | ||
return false; | ||
} | ||
return true; | ||
} | ||
const BLOCK_LEN = 16; | ||
@@ -73,3 +56,3 @@ const IV = new Uint8Array(BLOCK_LEN); | ||
}, | ||
decodeStream: (r) => bytesToNumber(r.bytes((P.U16BE.decodeStream(r) + 7) >>> 3)), | ||
decodeStream: (r) => bytesToNumberBE(r.bytes((P.U16BE.decodeStream(r) + 7) >>> 3)), | ||
}); | ||
@@ -494,3 +477,3 @@ export const opaquempi = P.wrap({ | ||
async function getPublicPackets(edPriv, cvPriv, created = 0) { | ||
const edPub = bytesToNumber(concatBytes(new Uint8Array([0x40]), await ed25519.getPublicKey(edPriv))); | ||
const edPub = bytesToNumberBE(concatBytes(new Uint8Array([0x40]), await ed25519.getPublicKey(edPriv))); | ||
const edPubPacket = { | ||
@@ -501,3 +484,3 @@ created, | ||
const cvPoint = x25519.scalarMultBase(cvPriv); | ||
const cvPub = bytesToNumber(concatBytes(new Uint8Array([0x40]), cvPoint)); | ||
const cvPub = bytesToNumberBE(concatBytes(new Uint8Array([0x40]), cvPoint)); | ||
const cvPubPacket = { | ||
@@ -504,0 +487,0 @@ created, |
@@ -5,11 +5,10 @@ # ed25519-keygen | ||
Generation is deterministic and done in pure javascript, without CLI tools. | ||
Uses [noble-curves](https://github.com/paulmillr/noble-curves) under the hood. | ||
Includes SLIP-0010 / BIP32 HDKey implementation, | ||
sponsored by the Kin Foundation for [Kinetic](https://github.com/kin-labs/kinetic). | ||
- Pure JS, no CLI tools are involved | ||
- Can generate both deterministic and random keys | ||
- Uses [noble-curves](https://github.com/paulmillr/noble-curves) under the hood | ||
For the apps made with the library, check out: | ||
Includes SLIP-0010 (ed BIP32) HDKey implementation, funded by the Kin Foundation for | ||
[Kinetic](https://github.com/kin-labs/kinetic). For the apps made with the library, check out: | ||
[terminal7 WebRTC terminal multiplexer](https://github.com/tuzig/terminal7) | ||
- [terminal7 WebRTC terminal multiplexer](https://github.com/tuzig/terminal7) | ||
## Usage | ||
@@ -22,7 +21,12 @@ | ||
- [`ed25519-keygen/ssh`](#sshseed-username) for SSH key generation | ||
- [`ed25519-keygen/pgp`](#pgpseed-user-password) for [RFC 4880](https://datatracker.ietf.org/doc/html/rfc4880) + [RFC 6637](https://datatracker.ietf.org/doc/html/rfc6637) | ||
- [`ed25519-keygen/pgp`](#pgpseed-user-password) for | ||
[RFC 4880](https://datatracker.ietf.org/doc/html/rfc4880) + | ||
[RFC 6637](https://datatracker.ietf.org/doc/html/rfc6637) | ||
- [`ed25519-keygen/tor`](#torseed) for TOR onion addresses | ||
- [`ed25519-keygen/ipns`](#ipnsseed) for IPNS addresses | ||
- [`ed25519-keygen/hdkey`](#hdkey) for [SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md)/[BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) HDKey | ||
- [`ed25519-keygen/utils`](#randombyteslength) for cryptographically secure random number generator (CSPRNG) | ||
- [`ed25519-keygen/hdkey`](#hdkey) for | ||
[SLIP-0010](https://github.com/satoshilabs/slips/blob/master/slip-0010.md)/[BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) | ||
HDKey | ||
- [`ed25519-keygen/utils`](#randombyteslength) for cryptographically secure random number generator | ||
(CSPRNG) | ||
@@ -42,3 +46,4 @@ Use it in the following way: | ||
- `username: string` | ||
- Returns `{ fingerprint: string, privateKey: string, publicKey: string, publicKeyBytes: Uint8Array }` | ||
- Returns | ||
`{ fingerprint: string, privateKey: string, publicKey: string, publicKeyBytes: Uint8Array }` | ||
@@ -76,10 +81,12 @@ ```js | ||
Creates keys compatible with GPG. GPG is a commonly known utility that supports PGP protocol. Quirks: | ||
Creates keys compatible with GPG. GPG is a commonly known utility that supports PGP protocol. | ||
Quirks: | ||
1. Generated private and public keys would have different representation, | ||
however, **their fingerprints would be the same**. This is because AES encryption is used to | ||
hide the keys, and AES requires different IV / salt. | ||
1. Generated private and public keys would have different representation, however, **their | ||
fingerprints would be the same**. This is because AES encryption is used to hide the keys, and | ||
AES requires different IV / salt. | ||
2. The function is slow (~725ms on Apple M1), because it uses S2K to derive keys. | ||
3. "warning: lower 3 bits of the secret key are not cleared" | ||
happens even for keys generated with GnuPG 2.3.6, because check looks at item as Opaque MPI, when it is just MPI: see [bugtracker URL](https://dev.gnupg.org/rGdbfb7f809b89cfe05bdacafdb91a2d485b9fe2e0). | ||
3. "warning: lower 3 bits of the secret key are not cleared" happens even for keys generated with | ||
GnuPG 2.3.6, because check looks at item as Opaque MPI, when it is just MPI: see | ||
[bugtracker URL](https://dev.gnupg.org/rGdbfb7f809b89cfe05bdacafdb91a2d485b9fe2e0). | ||
@@ -158,2 +165,3 @@ ```js | ||
``` | ||
## `ipns(seed)` | ||
@@ -164,3 +172,4 @@ | ||
- `seed: Uint8Array` | ||
- Returns `{ privateKey: string, publicKey: string, base36: string, base32: string, base16: string, contenthash: string}` | ||
- Returns | ||
`{ privateKey: string, publicKey: string, base36: string, base32: string, base16: string, contenthash: string}` | ||
@@ -190,7 +199,13 @@ ```js | ||
SLIP-0010 hierarchical deterministic (HD) wallets for implementation. Based on audited code from [scure-bip32](https://github.com/paulmillr/scure-bip32). Check out [scure-bip39](https://github.com/paulmillr/scure-bip39) if you also need mnemonic phrases. | ||
SLIP-0010 hierarchical deterministic (HD) wallets for implementation. Based on code from | ||
[scure-bip32](https://github.com/paulmillr/scure-bip32). Check out | ||
[scure-bip39](https://github.com/paulmillr/scure-bip39) if you also need mnemonic phrases. | ||
- SLIP-0010 publicKey is 33 bytes (see [this issue](https://github.com/satoshilabs/slips/issues/1251)), if you want 32-byte publicKey, use `.publicKeyRaw` getter | ||
- SLIP-0010 publicKey is 33 bytes (see | ||
[this issue](https://github.com/satoshilabs/slips/issues/1251)), if you want 32-byte publicKey, | ||
use `.publicKeyRaw` getter | ||
- SLIP-0010 vectors fingerprint is actually `parentFingerprint` | ||
- SLIP-0010 doesn't allow deriving non-hardened keys for Ed25519, however some other libraries treat non-hardened keys (`m/0/1`) as hardened (`m/0'/1'`). If you want this behaviour, there is a flag `forceHardened` in `derive` method | ||
- SLIP-0010 doesn't allow deriving non-hardened keys for Ed25519, however some other libraries treat | ||
non-hardened keys (`m/0/1`) as hardened (`m/0'/1'`). If you want this behaviour, there is a flag | ||
`forceHardened` in `derive` method | ||
@@ -209,4 +224,4 @@ ```ts | ||
Note: `chainCode` property is essentially a private part | ||
of a secret "master" key, it should be guarded from unauthorized access. | ||
Note: `chainCode` property is essentially a private part of a secret "master" key, it should be | ||
guarded from unauthorized access. | ||
@@ -240,9 +255,13 @@ The full API is: | ||
### `randomBytes(length)` | ||
## utils | ||
- `byteLength: number` default is `32` | ||
- Returns `Uint8Array` filled with cryptographically secure random bytes | ||
```ts | ||
import { randomBytes } from 'ed25519-keygen/utils'; | ||
const key = randomBytes(32); | ||
``` | ||
CSPRNG for secure generation of random Uint8Array. Utilizes webcrypto under the hood. | ||
## License | ||
MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file. |
import { ed25519 } from '@noble/curves/ed25519'; | ||
import { concatBytes } from '@noble/hashes/utils'; | ||
import { hex, base32, utils } from '@scure/base'; | ||
import { concatBytes } from 'micro-packed'; | ||
@@ -5,0 +5,0 @@ const base36 = utils.chain( |
import { ed25519, x25519 } from '@noble/curves/ed25519'; | ||
import { bytesToNumberBE, equalBytes, numberToHexUnpadded } from '@noble/curves/abstract/utils'; | ||
import { crypto } from '@noble/hashes/crypto'; | ||
import { ripemd160 } from '@noble/hashes/ripemd160'; | ||
import { sha1 } from '@noble/hashes/sha1'; | ||
import { ripemd160 } from '@noble/hashes/ripemd160'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { sha512 } from '@noble/hashes/sha512'; | ||
import { sha3_256 } from '@noble/hashes/sha3'; | ||
import { CHash } from '@noble/hashes/utils'; | ||
import { randomBytes } from '@noble/hashes/utils'; | ||
import { crypto } from '@noble/hashes/crypto'; | ||
import { CHash, concatBytes, randomBytes } from '@noble/hashes/utils'; | ||
import { utf8, hex } from '@scure/base'; | ||
import * as P from 'micro-packed'; | ||
import { concatBytes } from 'micro-packed'; | ||
import { utf8, hex } from '@scure/base'; | ||
export type Bytes = Uint8Array; | ||
function numberToHexUnpadded(num: number | bigint): string { | ||
let hex = num.toString(16); | ||
hex = hex.length & 1 ? `0${hex}` : hex; | ||
return hex; | ||
} | ||
function bytesToNumber(bytes: Uint8Array): bigint { | ||
return BigInt('0x' + hex.encode(bytes)); | ||
} | ||
// todo: const-time? | ||
function equalBytes(a: Uint8Array, b: Uint8Array): boolean { | ||
if (a.length !== b.length) return false; | ||
for (let i = 0; i < a.length; i++) { | ||
if (a[i] !== b[i]) return false; | ||
} | ||
return true; | ||
} | ||
// RFCS: | ||
@@ -93,3 +73,3 @@ // - main: https://datatracker.ietf.org/doc/html/rfc4880 | ||
decodeStream: (r: P.Reader): bigint => | ||
bytesToNumber(r.bytes((P.U16BE.decodeStream(r) + 7) >>> 3)), | ||
bytesToNumberBE(r.bytes((P.U16BE.decodeStream(r) + 7) >>> 3)), | ||
}); | ||
@@ -599,3 +579,3 @@ | ||
async function getPublicPackets(edPriv: Bytes, cvPriv: Bytes, created = 0) { | ||
const edPub = bytesToNumber( | ||
const edPub = bytesToNumberBE( | ||
concatBytes(new Uint8Array([0x40]), await ed25519.getPublicKey(edPriv)) | ||
@@ -608,3 +588,3 @@ ); | ||
const cvPoint = x25519.scalarMultBase(cvPriv); | ||
const cvPub = bytesToNumber(concatBytes(new Uint8Array([0x40]), cvPoint)); | ||
const cvPub = bytesToNumberBE(concatBytes(new Uint8Array([0x40]), cvPoint)); | ||
const cvPubPacket = { | ||
@@ -611,0 +591,0 @@ created, |
import { ed25519 } from '@noble/curves/ed25519'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { concatBytes } from 'micro-packed'; | ||
import { concatBytes, randomBytes } from '@noble/hashes/utils'; | ||
import { base64 } from '@scure/base'; | ||
import * as P from 'micro-packed'; | ||
import { base64 } from '@scure/base'; | ||
import { randomBytes } from '@noble/hashes/utils'; | ||
@@ -8,0 +7,0 @@ export const SSHString = P.string(P.U32BE); |
import { ed25519 } from '@noble/curves/ed25519'; | ||
import { sha3_256 } from '@noble/hashes/sha3'; | ||
import { concatBytes } from '@noble/hashes/utils'; | ||
import { utf8, base32, base64 } from '@scure/base'; | ||
import { concatBytes } from 'micro-packed'; | ||
@@ -6,0 +6,0 @@ const ADDRESS_VERSION = new Uint8Array([0x03]); |
import { ed25519 } from '@noble/curves/ed25519'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { concatBytes } from 'micro-packed'; | ||
import { concatBytes, randomBytes } from '@noble/hashes/utils'; | ||
import { base64 } from '@scure/base'; | ||
import * as P from 'micro-packed'; | ||
import { base64 } from '@scure/base'; | ||
import { randomBytes } from '@noble/hashes/utils'; | ||
export const SSHString = P.string(P.U32BE); | ||
@@ -8,0 +7,0 @@ export const SSHBuf = P.bytes(P.U32BE); |
import { ed25519 } from '@noble/curves/ed25519'; | ||
import { sha3_256 } from '@noble/hashes/sha3'; | ||
import { concatBytes } from '@noble/hashes/utils'; | ||
import { utf8, base32, base64 } from '@scure/base'; | ||
import { concatBytes } from 'micro-packed'; | ||
const ADDRESS_VERSION = new Uint8Array([0x03]); | ||
@@ -6,0 +6,0 @@ export function formatPublicKey(pubBytes) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
259
89389
2002