
監査済みで最小限の楕円曲線暗号のJS実装。
監査済みで最小限の楕円曲線暗号のJS実装。
各曲線には5kbの姉妹プロジェクトがあります secp256k1 と ed25519。 これらは攻撃対象領域が小さいですが、機能は少なくなっています。
noble cryptography — 高セキュリティで監査が容易な、自己完結型の暗号ライブラリとツールのセット。
npm install @noble/curves
deno add jsr:@noble/curves
すべての主要なプラットフォームとランタイムをサポートしています。 React Nativeでは、getRandomValuesのpolyfillが必要になる場合があります。 スタンドアロンファイル noble-curves.js も利用可能です。```js // import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size import { secp256k1 } from '@noble/curves/secp256k1.js'; const { secretKey, publicKey } = secp256k1.keygen(); const msg = new TextEncoder().encode('hello noble'); const sig = secp256k1.sign(msg, secretKey); const isValid = secp256k1.verify(sig, msg, publicKey);
- [ECDSA、EdDSA、Schnorr署名](#ecdsa-eddsa-schnorr-signatures)
- [ECDH: Diffie-Hellman共有秘密](#ecdh-diffie-hellman-shared-secrets)
- [webcrypto: フレンドリーなラッパー](#webcrypto-friendly-wrapper)
- [BLS署名、bls12-381、bn254別名alt\_bn128](#bls-signatures-bls12-381-bn254-aka-alt_bn128)
- [hash-to-curve: 曲線点へのハッシュ](#hash-to-curve-hashing-to-curve-points)
- [OPRF](#oprfs) | [FROST閾値署名](#frost-threshold-signatures)
- [poseidon: Poseidonハッシュ](#poseidon-poseidon-hash) | [fft: 高速フーリエ変換](#fft-fast-fourier-transform) | [utils](#utils-byte-shuffling-conversion)
- 内部: [点演算](#elliptic-curve-point-math) | [modular](#modular-modular-arithmetics--finite-fields) | [カスタム曲線](#weierstrass-custom-weierstrass-curve--ecdsa)
- [仕様](#specs)
- [セキュリティ](#security) | [速度](#speed) | [アップグレード](#upgrading) | [コントリビューションとテスト](#contributing--testing) | [ライセンス](#license)
### ECDSA、EdDSA、Schnorr署名
#### secp256k1、p256、p384、p521、ed25519、ed448、brainpool```js
import { secp256k1, schnorr } from '@noble/curves/secp256k1.js';
import { p256, p384, p521 } from '@noble/curves/nist.js';
import { ed25519 } from '@noble/curves/ed25519.js';
import { ed448 } from '@noble/curves/ed448.js';
import { brainpoolP256r1, brainpoolP384r1, brainpoolP512r1 } from '@noble/curves/misc.js';
for (const curve of [
secp256k1, schnorr,
p256, p384, p521,
ed25519, ed448,
brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
]) {
const { secretKey, publicKey } = curve.keygen();
const msg = new TextEncoder().encode('hello noble');
const sig = curve.sign(msg, secretKey);
const isValid = curve.verify(sig, msg, publicKey);
console.log(curve, secretKey, publicKey, sig, isValid);
}
// Specific private key
import { hexToBytes } from '@noble/curves/utils.js';
const secret2 = hexToBytes('46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236');
const pub2 = secp256k1.getPublicKey(secret2);
メッセージは常に最初にハッシュ化されます: prehashed signingを参照してください。 ECDSAは決定論的kを使用し、EdDSAはRFC 8032に準拠し、Schnorr(secp256k1のみ)はBIP 340に準拠します: Specsを参照してください。
MuSig2署名スキームとsecp256k1用のBIP324 ElligatorSwiftマッピングは 別のパッケージで利用可能です。
import { ristretto255, ristretto255_hasher, ristretto255_oprf } from '@noble/curves/ed25519.js'; import { decaf448, decaf448_hasher, decaf448_oprf } from '@noble/curves/ed448.js';
console.log(ristretto255.Point, decaf448.Point);
[RFC 9496](https://www.rfc-editor.org/rfc/rfc9496) で ristretto255 と decaf448 の詳細を確認してください。
[Point](#elliptic-curve-point-math)、[hasher](#hash-to-curve-hashing-to-curve-points)、[oprf](#oprfs) の個別ドキュメントも確認してください。
#### 事前ハッシュ署名```js
import { secp256k1 } from '@noble/curves/secp256k1.js';
import { keccak_256 } from '@noble/hashes/sha3.js';
const { secretKey } = secp256k1.keygen();
const msg = new TextEncoder().encode('hello noble');
// prehash: true (default) - hash using secp256k1.hash (sha256)
const sig = secp256k1.sign(msg, secretKey);
// prehash: false - hash using custom hash
const sigKeccak = secp256k1.sign(keccak_256(msg), secretKey, { prehash: false });
デフォルトでは(prehash: true)、sign() と verify() はまずメッセージに曲線の組み込みハッシュを適用します:
secp256k1 には sha256、p521 には sha512。prehash: false を使用するとカスタムハッシュ
(例:secp256k1 + keccak_256)を使用できます。noble-curves v1 では、prehash: false がデフォルトでした。
import { secp256k1 } from '@noble/curves/secp256k1.js'; const { secretKey, publicKey } = secp256k1.keygen(); const msg = new TextEncoder().encode('hello noble'); const sigRec = secp256k1.sign(msg, secretKey, { format: 'recovered' }); const publicKey_ = secp256k1.recoverPublicKey(sigRec, msg); // == publicKey
// recovered sig is compact sig with an extra byte const sigNoRec = secp256k1.sign(msg, secretKey, { format: 'compact' }); // sigNoRec == sigRec.slice(1)
// Signature instance const sigInstance = secp256k1.Signature.fromBytes(sigRec, 'recovered');
公開鍵復元はECDSAでのみサポートされています。これは単純な数学的操作です。
署名が実際に行われたという保証はありません。偽造された (r, s, h) はランダムな公開鍵に復元されますが、この特定の偽造された h につながる m を見つけることは現実的ではありません。
#### ノイズを用いたヘッジ付きECDSA```js
import { secp256k1 } from '@noble/curves/secp256k1.js';
const { secretKey } = secp256k1.keygen();
const msg = new TextEncoder().encode('hello noble');
// extraEntropy: false - default, hedging disabled
const sigNoisy = secp256k1.sign(msg, secretKey);
// extraEntropy: true - fetch 32 random bytes from CSPRNG
const sigNoisyA = secp256k1.sign(msg, secretKey, { extraEntropy: true });
// extraEntropy: bytes - specific extra entropy
const ent = Uint8Array.from([0xca, 0xfe, 0x01, 0x23]);
const sigNoisy2 = secp256k1.sign(msg, secretKey, { extraEntropy: ent });
デフォルトでは、ECDSA署名は決定論的です(RFC 6979)。純粋に決定論的な署名はフォールト攻撃に対して脆弱であるため、BIP340 schnorrのような新しいスキームでは、署名生成にランダム性を取り入れています。これはヘッジングとも呼ばれます。extraEntropyはヘッジモードを有効にします。詳細については、Deterministic signatures are not your friendsをご覧ください。
import { ed25519 } from '@noble/curves/ed25519.js'; const { secretKey, publicKey } = ed25519.keygen(); const msg = new TextEncoder().encode('hello noble'); const sig = ed25519.sign(msg, secretKey); // zip215: true const isValid = ed25519.verify(sig, msg, publicKey); // SBS / e-voting / RFC8032 / FIPS 186-5 const isValidRfc = ed25519.verify(sig, msg, publicKey, { zip215: false });
* `zip215: true`(デフォルト)は、[ZIP215](https://zips.z.cash/zip-0215) で定義された、より寛容で[コンセンサスに優しい](https://hdevalence.ca/blog/2020-10-04-its-25519am)検証ルールを使用します。
* `zip215: false` は厳格な RFC 8032 / FIPS 186-5 検証を強制し、SBS ベースの
否認防止を追加します。これは契約署名、電子投票、ブロックチェーンに有用です。
どちらのモードも SUF-CMA(選択メッセージ攻撃に対する強存在的偽造不可能性)を備えています。
他のほとんどのライブラリは SUF-CMA も SBS も備えていません。
詳細は [Taming the many EdDSAs](https://eprint.iacr.org/2020/1244) を参照してください。
### ECDH: Diffie-Hellman 共有秘密```js
import { x25519 } from '@noble/curves/ed25519.js';
const alice = x25519.keygen();
const bob = x25519.keygen();
const sharedKey = x25519.getSharedSecret(alice.secretKey, bob.publicKey);
// Same API: secp256k1, p256, p384, p521, x448
// converting ed25519 keys to x25519
import { ed25519 } from '@noble/curves/ed25519.js';
const alice2 = ed25519.keygen();
const bob2 = ed25519.keygen();
const aliceSecX = ed25519.utils.toMontgomerySecret(alice2.secretKey);
const bobPubX = ed25519.utils.toMontgomery(bob2.publicKey);
const sharedKey2 = x25519.getSharedSecret(aliceSecX, bobPubX);
すべてのWeierstrass曲線、および2つのMontgomery曲線 X25519 (Curve25519) と X448 (Curve448) 上でECDHを提供し、RFC 7748 に準拠しています。
Weierstrass曲線では、共有秘密は:
key.slice(1) を使用してそれを除去しますsha256(shared) や hkdf(shared) のように、その上でハッシュ化またはKDFを使用しますimport { ed25519, x25519 } from '@noble/curves/webcrypto.js';
// signatures: p256, p384, p521, ed25519, ed448 const keys = await ed25519.keygen(); const msg = new TextEncoder().encode('hello noble'); const sig = await ed25519.sign(msg, keys.secretKey); const isValid = await ed25519.verify(sig, msg, keys.publicKey);
// ECDH: p256, p384, p521, x25519, x448 const alice = await x25519.keygen(); const bob = await x25519.keygen(); const shared = await x25519.getSharedSecret(alice.secretKey, bob.publicKey);
// key conversion between noble (raw) and webcrypto (pkcs8 / spki) formats import { p256 as p256n } from '@noble/curves/nist.js'; import { p256 } from '@noble/curves/webcrypto.js'; const nobleKeys = p256n.keygen(); const secretKeyPkcs8 = await p256.utils.convertSecretKey(nobleKeys.secretKey, 'raw', 'pkcs8'); const publicKeySpki = await p256.utils.convertPublicKey(nobleKeys.publicKey, 'raw', 'spki');
組み込みのWebCryptoを薄くラップし、noble APIを模倣しています。メソッドは常に非同期です。
ランタイムのサポートは異なります - `await curve.isSupported()` で確認してください。
純粋なJSの鍵変換ユーティリティについては、[micro-key-producer](https://github.com/paulmillr/micro-key-producer) をチェックしてください。
### BLS署名、bls12-381、bn254 別名 alt_bn128```ts
import { bls12_381 } from '@noble/curves/bls12-381.js';
// G1 pubkeys, G2 sigs
const blsl = bls12_381.longSignatures;
const { secretKey, publicKey } = blsl.keygen();
const msg = new TextEncoder().encode('hello noble');
const msgp = blsl.hash(msg); // hash to point, default DST
const msgpd = blsl.hash(msg, 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_'); // custom DST (Ethereum)
const signature = blsl.sign(msgp, secretKey);
const isValid = blsl.verify(signature, msgp, publicKey);
// G1 sigs, G2 pubkeys: identical API
const blss = bls12_381.shortSignatures;
// Aggregation
const aggregatedKey = blsl.aggregatePublicKeys([
blsl.getPublicKey(bls12_381.utils.randomSecretKey()),
blsl.getPublicKey(bls12_381.utils.randomSecretKey()),
]);
// const aggregatedSig = blsl.aggregateSignatures(sigs)
// Pairings: bls12_381.pairing(PointG1, PointG2)
// Fields: bls12_381.fields.Fp, Fp2, Fp12, Fr
例えば、BLS EVMプリコンパイルの実装を参照してください。
BN254 APIはbls12-381を反映しています。この曲線は以前alt_bn128と呼ばれていました。 この実装はEIP-196および EIP-197と互換性があります: bn254 EVMプリコンパイルの実装を参照してください。 bn254の点はtoBytesを実装していません。シリアライゼーション標準が存在しないためです: 実装はエンディアン、フラグ、G2の虚部の順序で分岐します。 代わりにbigintから点を初期化してください。
import { secp256k1_hasher } from '@noble/curves/secp256k1.js';
const msg = Uint8Array.from([0xca, 0xfe, 0x01, 0x23]); const point = secp256k1_hasher.hashToCurve(msg); const pointDst = secp256k1_hasher.hashToCurve(msg, { DST: 'hello noble' }); const pointNu = secp256k1_hasher.encodeToCurve(msg); const scalar = secp256k1_hasher.hashToScalar(msg);
// Same API: p256_hasher, p384_hasher, p521_hasher (nist.js), // ed25519_hasher, ristretto255_hasher (ed25519.js), ed448_hasher, decaf448_hasher (ed448.js), // bls12_381.G1, bls12_381.G2. // ristretto255 & decaf448 also provide deriveToCurve.
// abstract methods import { expand_message_xmd, expand_message_xof, hash_to_field } from '@noble/curves/abstract/hash-to-curve.js';
モジュールは任意の文字列を楕円曲線上の点にハッシュ化できるようにします。[RFC 9380](https://www.rfc-editor.org/rfc/rfc9380) を実装しています。
`_hasher` 名前空間はツリーシェイキングのために曲線とは分離されています:
hash-to-curve を必要としないユーザーのビルドには含まれません。
### OPRFs```js
import { p256_oprf, p384_oprf, p521_oprf } from '@noble/curves/nist.js';
import { ristretto255_oprf } from '@noble/curves/ed25519.js';
import { decaf448_oprf } from '@noble/curves/ed448.js';
我々は、RFC 9497 に準拠した OPRF(oblivious pseudorandom functions)を提供します。
OPRF は、Output = PRF(Input, serverSecretKey) を対話的に生成することを可能にします:
FROST は RFC 9591 しきい値 Schnorr 署名を実装しています。
アプリケーションの観点からはマルチシグに似ています:max 人中 min 人の参加者が
共同で共有公開鍵の下で1つの Schnorr 署名を生成できます。
サポートされる暗号スイートは p256_FROST、ed25519_FROST、ed448_FROST、ristretto255_FROST、
secp256k1_FROST、および schnorr_FROST(Taproot 互換の secp256k1)です。
署名は2ラウンドで行われます:選択された署名者が最初にコミットし、その後署名シェアを生成します。```js
import { p256_FROST } from '@noble/curves/nist.js';
const signers = { min: 2, max: 3 }; const alice = p256_FROST.Identifier.derive('[email protected]'); const bob = p256_FROST.Identifier.derive('[email protected]'); const carol = p256_FROST.Identifier.derive('[email protected]'); // trusted dealer const deal = p256_FROST.trustedDealer(signers, [alice, bob, carol]); for (const id of [alice, bob, carol]) p256_FROST.validateSecret(deal.secretShares[id], deal.public);
const msg = new TextEncoder().encode('hello threshold'); // round 1: selected signers commit const aliceRound1 = p256_FROST.commit(deal.secretShares[alice]); const bobRound1 = p256_FROST.commit(deal.secretShares[bob]); const commitmentList = [aliceRound1.commitments, bobRound1.commitments]; // round 2: signers produce signature shares const sigShares = { [alice]: https://raw.githubusercontent.com/paulmillr/noble-curves/main/p256_FROST.signShare( deal.secretShares[alice], deal.public, aliceRound1.nonces, commitmentList, msg ), [bob]: https://raw.githubusercontent.com/paulmillr/noble-curves/main/p256_FROST.signShare( deal.secretShares[bob], deal.public, bobRound1.nonces, commitmentList, msg ), }; const sig = p256_FROST.aggregate(deal.public, commitmentList, msg, sigShares); const isValid = p256_FROST.verify(sig, msg, deal.public.commitments[0]);
鍵生成は、信頼できるディーラー(上記)または DKG(分散鍵生成)で行えます。
DKG には 3 つのラウンドがあります。参加者が鍵生成にコミットし、秘密シェアを交換し、
その後、最終的な参加者鍵を導出します - [テスト](https://github.com/paulmillr/noble-curves/blob/main/test/rfc9591-frost.test.ts) の
`DKG.round1` / `round2` / `round3` の使用例を参照してください。
このライブラリは暗号処理のステップを実装しており、周辺のアプリケーションプロトコルは実装していません。
呼び出し側は依然として、認証された通信、調整、リトライ、セッション管理、ポリシーを用意する必要があります。
### poseidon: Poseidon ハッシュ
[Poseidon](https://www.poseidon-hash.info) ZK フレンドリーなハッシュを実装しています。
置換とスポンジです。
poseidon には異なる定数を持つ多くのバリアントがあります。
それらは提供していません。手動で構築する必要があります。
適切な例については [scure-starknet](https://github.com/paulmillr/scure-starknet) パッケージを参照してください。```ts
import { bn254 } from '@noble/curves/bn254.js';
import { grainGenConstants, poseidon, poseidonSponge } from '@noble/curves/abstract/poseidon.js';
const rate = 2;
const capacity = 1;
const Fp = bn254.fields.Fr;
const { mds, roundConstants } = grainGenConstants({
Fp,
t: rate + capacity,
roundsFull: 8,
roundsPartial: 31,
});
const opts = {
Fp,
rate,
capacity,
sboxPower: 17,
mds,
roundConstants,
roundsFull: 8,
roundsPartial: 31,
};
const permutation = poseidon({ ...opts, t: rate + capacity });
const sponge = poseidonSponge(opts); // use carefully, not specced
import * as fft from '@noble/curves/abstract/fft.js'; import { bls12_381 } from '@noble/curves/bls12-381.js'; const Fr = bls12_381.fields.Fr; const roots = fft.rootsOfUnity(Fr, 7n); const fftFr = fft.FFT(roots, Fr);
有限体上の NTT / FFT (高速フーリエ変換)。
### utils: バイトシャッフリング、変換```ts
import { bytesToHex, concatBytes, equalBytes, hexToBytes } from '@noble/curves/utils.js';
bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23]));
hexToBytes('cafe0123');
concatBytes(Uint8Array.from([0xca, 0xfe]), Uint8Array.from([0x01, 0x23]));
equalBytes(Uint8Array.of(0xca), Uint8Array.of(0xca));
import { secp256k1 } from '@noble/curves/secp256k1.js'; const { Point } = secp256k1; const { BASE, ZERO, Fp, Fn } = Point; const p = BASE.multiply(2n);
// Math const p1 = p.add(p); const p2 = p.double(); const p3 = p.subtract(p); const p4 = p.negate(); const p5 = p.multiply(451n);
// MSM (multi-scalar multiplication) import { pippenger } from '@noble/curves/abstract/curve.js'; const pa = [BASE, BASE.multiply(2n), BASE.multiply(4n), BASE.multiply(8n)]; const p6 = pippenger(Point, pa, [3n, 5n, 7n, 11n]); // == BASE.multiply(129n)
// Cofactor const pcl = p.clearCofactor(); const isTorsionFree = p.isTorsionFree();
// Conversions const bytes = p.toBytes(); const p_ = Point.fromBytes(bytes); const { x, y } = p.toAffine(); const p__ = Point.fromAffine({ x, y });
各曲線は自身の Point クラスを公開しています: secp256k1、schnorr、p256、p384、p521、ed25519、ed448、
ristretto255、decaf448、bls12_381.G1 / G2、bn254.G1、jubjub、babyjubjub。
Weierstrass 点は射影(同次)座標 `new Point(X, Y, Z)` を使用し、
edwards 点は拡張座標 `new Point(X, Y, Z, T)` を使用します。どちらも x=X/Z、y=Y/Z です。
#### modular: モジュラー演算と有限体```js
import { mod, invert, Field } from '@noble/curves/abstract/modular.js';
// Finite Field utils
const fp = Field(2n ** 255n - 19n); // Finite field over 2^255-19
fp.mul(591n, 932n); // multiplication
fp.pow(481n, 11024858120n); // exponentiation
fp.div(5n, 17n); // division: 5/17 mod 2^255-19 == 5 * invert(17)
fp.inv(5n); // modular inverse
fp.sqrt(4n); // square root
// Non-Field generic utils are also available
mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10
invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse
すべての算術演算は、modular サブモジュールで定義された有限体上の JS bigint を用いて行われます。
体の演算は定数時間ではありません: security を参照してください。
この事実はほとんど無関係ですが、念頭に置くべき重要なメソッドは pow であり、これは素朴に使用すると指数のビットが漏洩する可能性があります。
import { weierstrass, ecdsa } from '@noble/curves/abstract/weierstrass.js'; import { sha256 } from '@noble/hashes/sha2.js'; // NIST secp192r1 aka p192. https://www.secg.org/sec2-v2.pdf const p192_CURVE = { p: 0xfffffffffffffffffffffffffffffffeffffffffffffffffn, n: 0xffffffffffffffffffffffff99def836146bc9b1b4d22831n, h: 1n, a: 0xfffffffffffffffffffffffffffffffefffffffffffffffcn, b: 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1n, Gx: 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012n, Gy: 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811n, }; const p192_Point = weierstrass(p192_CURVE); const p192 = ecdsa(p192_Point, sha256);
const keys = p192.keygen(); const msg = new TextEncoder().encode('custom curve'); const sig = p192.sign(msg, keys.secretKey); const isValid = p192.verify(sig, msg, keys.publicKey);
Short Weierstrass 曲線の式は `y² = x³ + ax + b` です。`weierstrass` は引数として `a`、`b`、体の標数 `p`、曲線の位数 `n`、余因子 `h`、生成点の座標 `Gx`、`Gy` を受け取り、Point クラスを返します。`ecdsa` は Point クラスとハッシュ関数を組み合わせて署名スキームにします。
#### edwards: カスタム Edwards 曲線```js
import { edwards } from '@noble/curves/abstract/edwards.js';
const ed25519_CURVE = {
p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
h: 8n,
a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n,
};
const ed25519_Point = edwards(ed25519_CURVE);
Twisted Edwards曲線の式は ax² + y² = 1 + dx²y² です。
a、d、体の標数 p、曲線の位数 n(L と呼ばれることもあります)、
コファクター h、生成点の座標 Gx、Gy を指定する必要があります。
このライブラリは監査を受けています:
curve、modular、poseidon、weierstrass2026年4月から定期的なAI支援による自己監査を開始しました。
プロパティベース、クロスライブラリ、Wycheproofのテストベクターに対してテストされ、 GitHub CIでファジングされています。
異常な点を見つけた場合は、調査して報告してください。
私たちはアルゴリズム的な定数時間を目標としています。JITコンパイラ と ガベージコレクタ は、 スクリプト言語において「定数時間」のタイミング攻撃耐性を 達成することを極めて困難にします。つまり、他のどのJSライブラリも定数時間性を持ち得ません。 GCのない言語である静的に型付けされたRustでさえ、 一部のケースでは定数時間の達成をより困難にします。 絶対的なセキュリティを目標とするなら、ネイティブへのバインディングを含め、どのJSライブラリも使用しないでください。 低レベルのライブラリと言語を使用してください。
これらの制限の中で、秘密スカラー乗算は具体的で測定可能な特性を提供します:
multiply() はデータ難読化されたテーブルスキャンを伴う符号付き固定ウィンドウテーブルを使用します —
点演算の数と順序はスカラー値に依存しません。r を用いて s + r·n としてマスクされます。
これはコファクター1の曲線(p256、p384、p521、secp256k1)上のすべての乗算、およびすべての場所での基点乗算に適用されます。benchmark/ct.ts)が、
敵対的なスカラークラス(疎 vs 密、低ビット vs 高ビット、位数付近、ビットパターン)間でタイミングを比較します。
基点乗算はどの曲線でも識別可能なタイミングを示さず、ランダム点乗算はWeierstrass曲線で何も示しません
(1000サンプルで最大 |t| ≤ 2.8、閾値4.5)。既知の制限: コファクター付きEdwards曲線(ed25519、ed448)では、非基点を秘密スカラーで乗算する場合、 ブラインディングされません。同じハーネスがこれを確実に検出します。EdDSA署名は影響を受けず(ブラインドされた基点のみを乗算します)、 X25519/X448は別のMontgomery-ladder実装を使用します(これも影響を受けません)。これは、任意のEdwards/Ristretto点を 長期間存続する秘密スカラーで乗算するプロトコルにとって重要です。そのような場合は、構造上フル幅であるスカラーを優先してください。 孤立したハーネスでの検出可能性は、実用的な悪用可能性を意味しないことに注意してください。現実的な クロステナント/ブラウザ内設定でスカラー抽出を試みましたが、100,000のタイミングサンプルがあっても Edwardsスカラーを復元することはできませんでした。
絶対的なセキュリティを目標とするなら、JS / WASM の代わりに低レベルの言語を使用してください。
このライブラリは主にUint8Arrayとbigintを使用します。
.fill(0) があり、内容をゼロで埋めるよう指示しますが、
JSでは保証はありませんawait fn() はすべての内部変数をメモリに書き込みます。非同期関数では、
コードチャンクがいつ実行されるかの保証はありません。つまり、攻撃者は
メモリからデータを読み取る十分な時間を持つ可能性があります。これは、一部の秘密が予想よりも長くメモリに留まる可能性があることを意味します。 しかし、攻撃者がアプリケーションメモリを読み取れるなら、いずれにせよ手遅れです: プロセスメモリをダンプして機密データが残っていないことを検証する複雑なテストスイートなしには、 機密データのゼロ化について何も保証する方法はありません。JSの場合、それはすべてのブラウザ(モバイルを含む)を テストすることを意味します。そしてもちろん、このライブラリを利用する実際のアプリケーションで 同じテストスイートを使用しなければ役に立ちません。
このパッケージには1つの依存関係があり、いくつかの開発依存関係があります:
私たちは、暗号学的に安全なPRNGと見なされる組み込みの
crypto.getRandomValues に依存しています。
ブラウザは過去に弱点を持っていました — そして再び持つ可能性もあります — が、ユーザー空間のCSPRNGを実装するのはさらに悪いことです。 なぜなら、高品質なエントロピーの信頼できるユーザー空間の供給源が存在しないからです。
暗号学的に関連する量子コンピュータが構築されれば、Shorのアルゴリズムを使用して 楕円曲線暗号(ECDSA / EdDSA と ECDH の両方)を破ることが可能になります。
SPHINCS+ など、より新しい/ハイブリッドなアルゴリズムへの切り替えを検討してください。それらは noble-post-quantum で利用可能です。
NISTは古典暗号(RSA、DSA、ECDSA、ECDH)を2035年以降禁止しています。オーストラリアのASDは2030年以降禁止しています。
npm run benchmark
noble-curvesは、20MB以上のベースポイント事前計算を生成するのに10ms以上を費やします。
これはカーブごとに**一度だけ**行われます。
生成は、いずれかのメソッド(pubkey、sign、verify)が呼び出されるまで遅延されます。
ユーザーは `Point.BASE.precompute(windowSize, false)` を手動で呼び出すことで、事前計算の生成を強制できます。
ソースコードを確認してください。
Apple M4でのベンチマーク結果:```
# algorithm=getPublicKey
ed25519 7,299 ops/sec · 137 μs/op
secp256k1 4,872 ops/sec · 205 μs/op · -1.5x
p256 4,724 ops/sec · 212 μs/op · -1.5x
bls12_381 (long, G2 sig) 3,466 ops/sec · 288 μs/op · -2.1x
ed448 3,224 ops/sec · 310 μs/op · -2.3x
p384 2,185 ops/sec · 458 μs/op · -3.3x
p521 1,221 ops/sec · 819 μs/op · -6x
bls12_381 (short, G1 sig) 1,070 ops/sec · 934 μs/op · -6.8x
# algorithm=sign
secp256k1 4,217 ops/sec · 237 μs/op
p256 4,116 ops/sec · 243 μs/op · ≈
ed25519 3,536 ops/sec · 283 μs/op · -1.2x
p384 1,992 ops/sec · 502 μs/op · -2.1x
ed448 1,577 ops/sec · 634 μs/op · -2.7x
p521 1,131 ops/sec · 884 μs/op · -3.7x
bls12_381 (short, G1 sig) 417 ops/sec · 2.39 ms/op · -10x
bls12_381 (long, G2 sig) 112 ops/sec · 8.88 ms/op · -37x
# algorithm=verify
ed25519 1,504 ops/sec · 665 μs/op
secp256k1 1,352 ops/sec · 739 μs/op · -1.1x
p256 917 ops/sec · 1.09 ms/op · -1.6x
ed448 546 ops/sec · 1.83 ms/op · -2.8x
p384 381 ops/sec · 2.62 ms/op · -3.9x
p521 187 ops/sec · 5.34 ms/op · -8x
bls12_381 (short, G1 sig) 100 ops/sec · 9.98 ms/op · -15x
bls12_381 (long, G2 sig) 77 ops/sec · 12.9 ms/op · -19x
# algorithm=getSharedSecret
ed25519 1,695 ops/sec · 590 μs/op
secp256k1 763 ops/sec · 1.31 ms/op · -2.2x
p256 737 ops/sec · 1.36 ms/op · -2.3x
ed448 599 ops/sec · 1.67 ms/op · -2.8x
p384 326 ops/sec · 3.06 ms/op · -5.2x
p521 176 ops/sec · 5.68 ms/op · -9.6x
サポートされている node.js バージョン:
v2 は内部構造を大幅に簡素化し、セキュリティを向上させ、バンドルサイズを削減し、将来への道筋をつけます。 私たちは v2 を可能な限り後方互換に保つよう努めました。
アップグレードパス: まず curves v1.9.x にアップグレードしてください。非推奨の警告を修正してから、v2 に切り替えてください。
モジュール:
.js 拡張子が必須になりました: @noble/curves/ed25519 => @noble/curves/ed25519.js。
これによりトランスパイラなしでネイティブのブラウザ利用が可能になりますp256、p384、p521 は nist に移動しました; jubjub は misc に移動しましたpasta と bn254_weierstrass (ペアリングベースではない bn254) 曲線は削除されました新機能:
isValidSecretKey、isValidPublicKey メソッド破壊的変更:
Point.fromHex は文字列専用になりました: Uint8Array には Point.fromBytes を使用してください{prehash: false}{lowS: false}{format: 'der'} で明示的に指定する必要があります。
これにより可鍛性が低減されますsignature.toBytes() を呼び出してくださいlongSignatures (G1 公開鍵、G2 署名) と shortSignatures (G1 署名、G2 公開鍵){message: ..., publicKey: ...}[] を期待するようになりましたweierstrass() + ecdsa() / 。
weierstrass / edwards は簡素化された曲線パラメータを期待します (Fp は p になりました);
ecdsa / eddsa は Point クラスとハッシュを期待します名前の変更 (curves v1.9 では古い名前が非推奨としてハイライトされます):
abstract/curve.js サブモジュール内の個別のメソッドPoint.BASE.multiply(Point.Fn.fromBytes(key))CURVE プロパティ => Point.CURVE()。
これは曲線パラメータのみを提供します*curve*_hasher。
例: secp256k1.hashToCurve => secp256k1_hasher.hashToCurve()削除された機能: Point#multiplyAndAddUnsafe、Point#hasEvenY、Field.MASK
npm install && npm run build && npm test でコードをビルドし、テストを実行します。
追加のスイートがあります: 低速な大スカラー / 大曲線テスト npm run test:slow、
および定数時間性ハーネス npm run benchmark:ct。
ライブラリに関連する有用なリソース、記事、 ドキュメント、デモについては paulmillr.com/noble を参照してください。
The MIT License (MIT)
Copyright (c) 2022 Paul Miller (https://paulmillr.com)
LICENSE ファイルを参照してください。
hash-to-curvemodularposeidonutilsweierstrass_shortw_utilssecp256k1edwards() + eddsa()