
अंडाकार वक्र क्रिप्टोग्राफी का ऑडिट किया गया और न्यूनतम JS कार्यान्वयन।
अंडरटेक किए गए और न्यूनतम एलिप्टिक कर्व क्रिप्टोग्राफी का JS कार्यान्वयन।
कर्व्स के 5kb सिस्टर प्रोजेक्ट हैं secp256k1 और ed25519। इनका हमले का क्षेत्र छोटा है, लेकिन सुविधाएँ कम हैं।
noble cryptography — उच्च-सुरक्षा, आसानी से ऑडिट किए जा सकने वाले संयमित क्रिप्टोग्राफिक लाइब्रेरीज़ और टूल्स का सेट।
npm install @noble/curves
deno add jsr:@noble/curves
हम सभी प्रमुख प्लेटफ़ॉर्म और रनटाइम का समर्थन करते हैं। React Native के लिए, आपको getRandomValues के लिए पॉलीफ़िल की आवश्यकता हो सकती है। एक स्टैंडअलोन फ़ाइल 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)
- [OPRFs](#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-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);
Messages को हमेशा पहले hash किया जाता है: देखें prehashed signing। ECDSA deterministic k का उपयोग करता है, EdDSA RFC 8032 का पालन करता है, Schnorr (केवल secp256k1) BIP 340 का पालन करता है: देखें Specs।
MuSig2 signature scheme और secp256k1 के लिए BIP324 ElligatorSwift mapping एक अलग package में उपलब्ध हैं।
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) के लिए अलग दस्तावेज़ देखें।
#### Prehashed signing```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() पहले संदेश पर curve के अंतर्निहित hash को लागू करते हैं:
secp256k1 के लिए sha256, p521 के लिए sha512। prehash: false एक कस्टम hash का उपयोग करने की अनुमति देता है
(जैसे 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');
Public key recovery केवल ECDSA के साथ समर्थित है। यह एक सरल गणितीय संक्रिया है:
इस बात की कोई गारंटी नहीं है कि हस्ताक्षर वास्तव में किया गया था। एक जाली (r, s, h) एक
यादृच्छिक सार्वजनिक कुंजी में परिवर्तित हो जाता है, लेकिन ऐसा m खोजना संभव नहीं है जो इस विशिष्ट जाली h की ओर ले जाए।
#### शोर के साथ Hedged 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` (डिफ़ॉल्ट) अधिक अनुमेय, [consensus-friendly](https://hdevalence.ca/blog/2020-10-04-its-25519am) सत्यापन नियमों का उपयोग करता है जो [ZIP215](https://zips.z.cash/zip-0215) में परिभाषित हैं।
* `zip215: false` सख्त RFC 8032 / FIPS 186-5 सत्यापन लागू करता है और SBS-आधारित
non-repudiation जोड़ता है, जो अनुबंध हस्ताक्षर, ई-वोटिंग और ब्लॉकचेन के लिए उपयोगी है।
दोनों मोड में SUF-CMA (strong unforgeability under chosen message attacks) है;
अधिकांश अन्य लाइब्रेरी में न तो SUF-CMA है और न ही SBS।
अधिक जानकारी के लिए [Taming the many EdDSAs](https://eprint.iacr.org/2020/1244) देखें।
### ECDH: Diffie-Hellman shared secrets```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 curves पर ECDH प्रदान करते हैं, और 2 Montgomery curves X25519 (Curve25519) और X448 (Curve448) पर, RFC 7748 के अनुरूप।
Weierstrass curves में, साझा secrets:
key.slice(1) का उपयोग करेंsha256(shared) या hkdf(shared)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 पर एक पतला wrapper, जो noble API की नकल करता है। विधियाँ हमेशा async होती हैं;
runtime समर्थन भिन्न होता है - `await curve.isSupported()` से जाँचें।
pure JS key conversion utils के लिए [micro-key-producer](https://github.com/paulmillr/micro-key-producer) देखें।
### BLS signatures, bls12-381, bn254 aka 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 precompiles का कार्यान्वयन देखें।
BN254 API bls12-381 की नकल करता है। इस curve को पहले alt_bn128 कहा जाता था। यह कार्यान्वयन EIP-196 और EIP-197 के साथ संगत है: bn254 EVM precompiles का कार्यान्वयन देखें। bn254 points toBytes को implement नहीं करते, क्योंकि कोई serialization standard नहीं है: कार्यान्वयन endianness, flags और G2 imaginary-part order पर भिन्न होते हैं। points को bigints से initialize करें।
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';
हम OPRFs (oblivious pseudorandom functions) प्रदान करते हैं, जो RFC 9497 के अनुरूप हैं।
OPRF इंटरैक्टिव रूप से Output = PRF(Input, serverSecretKey) बनाने की अनुमति देता है:
FROST RFC 9591 थ्रेशोल्ड Schnorr हस्ताक्षर को लागू करता है।
यह एप्लिकेशन के दृष्टिकोण से multisig के समान है: max प्रतिभागियों में से कोई भी min
एक साझा सार्वजनिक कुंजी के अंतर्गत संयुक्त रूप से एक Schnorr हस्ताक्षर उत्पन्न कर सकते हैं।
समर्थित ciphersuites हैं p256_FROST, ed25519_FROST, ed448_FROST, ristretto255_FROST,
secp256k1_FROST, और schnorr_FROST (Taproot-संगत secp256k1)।
हस्ताक्षर में दो राउंड होते हैं: चयनित हस्ताक्षरकर्ता पहले प्रतिबद्ध होते हैं, फिर हस्ताक्षर शेयर उत्पन्न करते हैं।```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 में तीन राउंड होते हैं: प्रतिभागी कुंजी निर्माण के लिए प्रतिबद्ध होते हैं, निजी शेयरों का आदान-प्रदान करते हैं,
फिर अंतिम प्रतिभागी कुंजियाँ प्राप्त करते हैं - [परीक्षणों](https://github.com/paulmillr/noble-curves/blob/main/test/rfc9591-frost.test.ts) में `DKG.round1` / `round2` / `round3` का उपयोग देखें।
लाइब्रेरी क्रिप्टोग्राफिक चरणों को लागू करती है, आसपास के एप्लिकेशन प्रोटोकॉल को नहीं:
कॉलर्स को अभी भी प्रमाणित संचार, समन्वय, पुनः प्रयास, सत्र प्रबंधन और नीति की आवश्यकता होती है।
### poseidon: Poseidon hash
[Poseidon](https://www.poseidon-hash.info) ZK-अनुकूल hash को लागू करता है:
permutation और sponge।
विभिन्न स्थिरांकों के साथ कई 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 बिंदु projective (homogeneous) निर्देशांक `new Point(X, Y, Z)` का उपयोग करते हैं,
edwards बिंदु extended निर्देशांक `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
सभी अंकगणित JS bigints के साथ परिमित क्षेत्रों पर किया जाता है,
जिसे modular सब-मॉड्यूल से परिभाषित किया जाता है।
फ़ील्ड संचालन स्थिर-समय नहीं हैं: 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 curve का सूत्र `y² = x³ + ax + b` है। `weierstrass` तर्कों के रूप में `a`, `b`, field characteristic `p`, curve order `n`, cofactor `h` और generator point के निर्देशांक `Gx`, `Gy` की अपेक्षा करता है, और एक Point class लौटाता है।
`ecdsa` एक Point class को hash function के साथ मिलाकर एक signature scheme बनाता है।
#### edwards: Custom Edwards curve```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, weierstrassहमने अप्रैल 2026 में नियमित AI-सहायित स्व-ऑडिट शुरू किए हैं।
इसका परीक्षण प्रॉपर्टी-आधारित, क्रॉस-लाइब्रेरी और Wycheproof वेक्टर के विरुद्ध किया जाता है, और इसे github ci में फ़ज़ किया जा रहा है।
यदि आपको कुछ असामान्य दिखे: जाँच करें और रिपोर्ट करें।
हम एल्गोरिथमिक स्थिर समय को लक्षित कर रहे हैं। JIT-कंपाइलर और Garbage Collector एक स्क्रिप्टिंग भाषा में "स्थिर समय" टाइमिंग अटैक प्रतिरोध प्राप्त करना अत्यंत कठिन बना देते हैं। जिसका अर्थ है कि किसी भी अन्य JS लाइब्रेरी में स्थिर-समयता नहीं हो सकती। यहाँ तक कि स्थिर रूप से टाइप की गई Rust, जो GC-रहित भाषा है, कुछ मामलों में स्थिर-समय प्राप्त करना कठिन बनाती है। यदि आपका लक्ष्य पूर्ण सुरक्षा है, तो किसी भी JS लाइब्रेरी का उपयोग न करें — नेटिव लाइब्रेरी के बाइंडिंग सहित। निम्न-स्तरीय लाइब्रेरी और भाषाओं का उपयोग करें।
इन सीमाओं के भीतर, गुप्त-स्केलर गुणन विशिष्ट, मापनीय गुण प्रदान करता है:
multiply() हस्ताक्षरित फिक्स्ड-विंडो टेबल के साथ
डेटा-अभेद्य टेबल स्कैन का उपयोग करता है — बिंदु संक्रियाओं की संख्या और क्रम
स्केलर मान से स्वतंत्र होते हैं।r के साथ s + r·n के रूप में अतिरिक्त रूप से मास्क किया जाता है। यह सहगुणक-1
वक्रों (p256, p384, p521, secp256k1) पर सभी गुणनों पर लागू होता है, और हर जगह आधार-बिंदु गुणनों पर।benchmark/ct.ts)
विरोधात्मक स्केलर वर्गों (विरल बनाम सघन, निम्न बनाम उच्च बिट, कोटि-निकट, बिट पैटर्न) में टाइमिंग की तुलना करता है। आधार-बिंदु गुणन किसी भी
वक्र पर कोई विभेदनीय टाइमिंग नहीं दिखाता, और यादृच्छिक-बिंदु गुणन Weierstrass वक्रों पर कोई नहीं दिखाता
(1000 नमूनों पर अधिकतम |t| ≤ 2.8; सीमा 4.5)।ज्ञात सीमा: सहगुणकित Edwards वक्रों (ed25519, ed448) पर, एक गैर-आधार बिंदु को गुप्त स्केलर से गुणा करना ब्लाइंड नहीं किया जाता। वही हार्नेस इसे विश्वसनीय रूप से पहचान लेता है। EdDSA हस्ताक्षरन अप्रभावित है (यह केवल ब्लाइंड किए गए आधार बिंदु को गुणा करता है), और X25519/X448 एक अलग Montgomery-लैडर कार्यान्वयन का उपयोग करते हैं (जो भी अप्रभावित है)। यह उन प्रोटोकॉल के लिए मायने रखता है जो मनमाने Edwards/Ristretto बिंदुओं को दीर्घकालिक गुप्त स्केलर से गुणा करते हैं; वहाँ निर्माण द्वारा पूर्ण-चौड़ाई वाले स्केलर को प्राथमिकता दें। ध्यान दें कि एक पृथक हार्नेस में पहचानने योग्यता का अर्थ व्यावहारिक शोषणीयता नहीं है: हमने एक यथार्थवादी क्रॉस-टेनेंट / इन-ब्राउज़र सेटिंग में स्केलर निष्कर्षण का प्रयास किया और 100,000 टाइमिंग नमूनों के साथ भी Edwards स्केलर को पुनर्प्राप्त करने में असमर्थ रहे।
यदि आपका लक्ष्य पूर्ण सुरक्षा है तो JS / WASM के बजाय निम्न-स्तरीय भाषाओं का उपयोग करें।
लाइब्रेरी अधिकतर Uint8Arrays और bigints का उपयोग करती है।
.fill(0) होता है जो सामग्री को शून्य से भरने का निर्देश देता है
लेकिन JS में कोई गारंटी नहीं हैawait fn() सभी आंतरिक चर को मेमोरी में लिख देगा। async फ़ंक्शन के साथ
कोई गारंटी नहीं है कि कोड चंक कब निष्पादित होगा। जिसका अर्थ है कि हमलावर के पास
मेमोरी से डेटा पढ़ने के लिए पर्याप्त समय हो सकता है।इसका अर्थ है कि कुछ रहस्य अपेक्षा से अधिक समय तक मेमोरी में रह सकते हैं। हालाँकि, यदि कोई हमलावर एप्लिकेशन मेमोरी पढ़ सकता है, तो यह वैसे भी बर्बाद है: संवेदनशील डेटा को शून्य करने के बारे में कुछ भी गारंटी देने का कोई तरीका नहीं है, बिना जटिल टेस्ट-सूट के जो प्रक्रिया मेमोरी को डंप करेगा और सत्यापित करेगा कि कोई संवेदनशील डेटा शेष नहीं है। JS के लिए इसका अर्थ है सभी ब्राउज़रों (मोबाइल सहित) का परीक्षण करना। और, निश्चित रूप से, यह लाइब्रेरी का उपभोग करने वाले वास्तविक एप्लिकेशन में उसी टेस्ट-सूट का उपयोग किए बिना बेकार होगा।
इस पैकेज के लिए, 1 निर्भरता है; और कुछ dev निर्भरताएँ:
हम अंतर्निहित
crypto.getRandomValues पर निर्भर हैं,
जिसे क्रिप्टोग्राफिक रूप से सुरक्षित PRNG माना जाता है।
ब्राउज़रों में अतीत में कमज़ोरियाँ रही हैं - और फिर हो सकती हैं - लेकिन userspace CSPRNG को लागू करना और भी बुरा है, क्योंकि उच्च-गुणवत्ता वाली एन्ट्रॉपी का कोई विश्वसनीय userspace स्रोत नहीं है।
क्रिप्टोग्राफिक रूप से प्रासंगिक क्वांटम कंप्यूटर, यदि बनाया गया, तो Shor के एल्गोरिथम का उपयोग करके दीर्घवृत्तीय वक्र क्रिप्टोग्राफी (ECDSA / EdDSA और ECDH दोनों) को तोड़ने की अनुमति देगा।
नए / हाइब्रिड एल्गोरिथम, जैसे SPHINCS+ पर स्विच करने पर विचार करें। वे noble-post-quantum में उपलब्ध हैं।
NIST शास्त्रीय क्रिप्टोग्राफी (RSA, DSA, ECDSA, ECDH) को 2035 के बाद प्रतिबंधित करता है। ऑस्ट्रेलियाई ASD इसे 2030 के बाद प्रतिबंधित करता है।
npm run benchmark
noble-curves को 20MB+ का base point precomputes जनरेट करने में 10+ ms लगते हैं।
यह प्रत्येक curve के लिए **एक बार** किया जाता है।
जनरेशन को तब तक टाला जाता है जब तक कोई भी method (pubkey, sign, verify) कॉल नहीं की जाती।
उपयोगकर्ता मैन्युअल रूप से `Point.BASE.precompute(windowSize, false)` कॉल करके precompute जनरेशन को बाध्य कर सकता है।
सोर्स कोड देखें।
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 pubkeys, G2 sigs) और shortSignatures (G1 sigs, G2 pubkeys){message: ..., publicKey: ...}[]नाम परिवर्तन (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,
और constant-timeness हार्नेस npm run benchmark:ct।
लाइब्रेरी से संबंधित उपयोगी संसाधनों, लेखों, दस्तावेज़ीकरण और डेमो के लिए paulmillr.com/noble देखें।
The MIT License (MIT)
Copyright (c) 2022 Paul Miller (https://paulmillr.com)
LICENSE फ़ाइल देखें।
curve, hash-to-curve, modular, poseidon, utils, weierstrass और
शीर्ष-स्तरीय मॉड्यूल _shortw_utils और secp256k1weierstrass() + ecdsa() / edwards() + eddsa()।
weierstrass / edwards सरलीकृत कर्व पैरामीटर की अपेक्षा करते हैं (Fp, p बन गया);
ecdsa / eddsa Point क्लास और हैश की अपेक्षा करते हैं