Skip to content
Noble ed25519. High-security, easily auditable, 0-dep, 1-file pubkey, scalarmult & EDDSA
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.travis.yml Fix travis. Jun 28, 2019
LICENSE Create noble-ed25519. Jun 20, 2019
README.md README: Add new noble project. Jul 9, 2019
index.d.ts Fix typo in the lib name. Jun 25, 2019
index.js Fix typo in the lib name. Jun 25, 2019
index.test.ts Remove expmod function. Remove prints. Jun 25, 2019
index.ts Fix typo in the lib name. Jun 25, 2019
package.json Release 0.1.1. Jun 28, 2019
tsconfig.json Create noble-ed25519. Jun 20, 2019

README.md

noble-ed25519

ed25519, an elliptic curve that could be used for assymetric encryption and EDDSA signature scheme.

This library belongs to noble crypto

noble-crypto — high-security, easily auditable set of contained cryptographic libraries and tools.

  • No dependencies, one small file
  • Easily auditable TypeScript/JS code
  • Uses es2019 bigint. Supported in Chrome, Firefox, node 10+
  • All releases are signed and trusted
  • Check out all libraries: secp256k1, ed25519, ripemd160, secretbox-aes-gcm

Usage

npm install noble-ed25519

import * as ed25519 from "noble-ed25519";

const PRIVATE_KEY = 0xa665a45920422f9d417e4867ef;
const HASH_MESSSAGE = new Uint8Array([99, 100, 101, 102, 103]);

(async () => {
  const publicKey = await ed25519.getPublicKey(PRIVATE_KEY);
  const signature = await ed25519.sign(HASH_MESSAGE, PRIVATE_KEY, publicKey);
  const isMessageSigned = await ed25519.verify(signature, HASH_MESSAGE, publicKey);
})();

API

function getPublicKey(privateKey: Uint8Array): Promise<Uint8Array>;
function getPublicKey(privateKey: string): Promise<string>;
function getPublicKey(privateKey: bigint): Promise<Point>;
  • privateKey: Uint8Array | string | bigint will be used to generate public key. Public key is generated by executing scalar multiplication of a base Point(x, y) by a fixed integer. The result is another Point(x, y) which we will by default encode to hex Uint8Array.
  • Returns:
    • Promise<Uint8Array> if Uint8Array was passed
    • Promise<string> if hex string was passed
    • Promise<Point(x, y)> instance if bigint was passed
    • Uses promises, because ed25519 uses sha internally; and we're using built-in browser window.crypto, which returns Promise.
function scalarmultBase(privateKey: Uint8Array): Uint8Array;
function scalarmultBase(privateKey: string): string;
function scalarmultBase(privateKey: bigint): Point;
  • privateKey: Uint8Array | string | bigint basically a number on which the lib will execute base point scalar multiplication.
  • Returns:
    • Uint8Array if Uint8Array was passed
    • string if hex string was passed
    • Point(x, y) instance if bigint was passed
function sign(hash: Uint8Array, privateKey: Uint8Array | bigint, k?: bigint): Promise<Uint8Array>;
function sign(hash: string, privateKey: string | bigint, k?: bigint): Promise<string>;
  • hash: Uint8Array - message hash which would be signed
  • privateKey: Uint8Array | bigint - private key which will sign the hash
  • publicKey: Uint8Array | Point - e.g. that was generated from privateKey by getPublicKey
  • Returns DER encoded EdDSA signature. You can consume it with SignResult.fromHex() method:
    • SignResult.fromHex(ed25519.sign(hash, privateKey, publicKey))
function verify(
  signature: Uint8Array | string | SignResult,
  hash: Uint8Array | string,
  publicKey: string | Point | Uint8Array
): Promise<boolean>
  • signature: Uint8Array - object returned by the sign function
  • hash: string | Uint8Array - message hash that needs to be verified
  • publicKey: string | Uint8Array | Point - e.g. that was generated from privateKey by getPublicKey
  • Returns Promise<boolean>: Promise<true> if signature == hash; otherwise Promise<false>

The library also exports helpers:

// 𝔽p
ed25519.P // 2 ^ 255 - 19

// Prime order
ed25519.PRIME_ORDER // 2 ^ 252 - 27742317777372353535851937790883648493

// Base point
ed25519.BASE_POINT // new ed25519.Point(x, y) where
// x = 15112221349535400772501151409588531511454012693041857206046113283949847762202n;
// y = 46316835694926478169428394003475163141307993866256225615783033603165251855960n;

// Elliptic curve point
ed25519.Point {
  constructor(x: bigint, y: bigint);
  toHex(): string;
}
secp256k1.SignResult {
  constructor(r: bigint, s: bigint);
  toHex(): string;
}

Security

Noble is production-ready & secure. Our goal is to have it audited by a good security expert.

We're using built-in JS BigInt, which is "unsuitable for use in cryptography" as per official spec. This means that the lib is vulnerable to timing attacks. But:

  1. JIT-compiler and Garbage Collector make "constant time" extremely hard to achieve in a scripting language.
  2. Which means any other JS library doesn't use constant-time bigints. Including bn.js or anything else. Even statically typed Rust, a language without GC, makes it harder to achieve constant-time for some cases.
  3. Overall they are quite rare; for our particular usage they're unimportant. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Try LibreSSL & similar low-level libraries & languages.
  4. We however consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading rootkits with every npm install. Our goal is to minimize this attack vector.

License

MIT (c) Paul Miller (https://paulmillr.com), see LICENSE file.

You can’t perform that action at this time.