@@ -94,81 +94,100 @@ type Hex = Uint8Array | string;
9494### getPublicKey
9595
9696``` ts
97- function getPublicKey(privateKey : Hex , isCompressed ? : boolean ): Uint8Array ;
97+ import { getPublicKey , utils , ProjectivePoint } from ' @noble/secp256k1' ;
98+ const privKey = utils .randomPrivateKey ();
99+ const pubKey33b = getPublicKey (privKey );
100+ const pubKey65b = getPublicKey (privKey , false );
101+ const pubKeyPoint = ProjectivePoint .fromPrivateKey (privKey );
102+ const samePoint = ProjectivePoint .fromHex (pubKeyPoint .toHex ());
98103```
99104
100- Generates 33-byte compressed public key from 32-byte private key.
101-
102- - If you need uncompressed 65-byte public key, set second argument to ` false ` .
103- - Use ` ProjectivePoint.fromPrivateKey(privateKey) ` for Point instance.
104- - Use ` ProjectivePoint.fromHex(publicKey) ` to convert Hex / Uint8Array into Point.
105+ Generates 33-byte compressed (default) or 65-byte public key from 32-byte private key.
105106
106107### sign
107108
108109``` ts
109- function sign(
110- messageHash : Hex , // message hash (not message) which would be signed
111- privateKey : Hex , // private key which will sign the hash
112- opts ? : { lowS : boolean ; extraEntropy : boolean | Hex } // optional params
113- ) : Signature ;
114- function signAsync(
115- messageHash : Hex ,
116- privateKey : Hex ,
117- opts ? : { lowS : boolean ; extraEntropy : boolean | Hex }
118- ) : Promise < Signature > ;
119-
120- sign (msgHash , privKey , { lowS: false }); // Malleable signature
121- sign (msgHash , privKey , { extraEntropy: true }); // Improved security
110+ import * as secp from ' @noble/secp256k1 ' ;
111+ import { sha256 } from ' @noble/hashes/sha256 ' ;
112+ import { utf8ToBytes } from ' @noble/hashes/utils ' ;
113+ const msg = ' noble cryptography ' ;
114+ const msgHash = sha256 ( utf8ToBytes ( msg )) ;
115+ const priv = secp . utils . randomPrivateKey ();
116+ const sigA = secp . sign ( msgHash , priv );
117+
118+ // Variants
119+ const sigB = await secp . signAsync ( msgHash , priv ) ;
120+ const sigC = secp . sign ( msgHash , priv , { extraEntropy: true }); // hedged sig
121+ const sigC2 = secp . sign (msgHash , priv , { extraEntropy: Uint8Array . from ([ 0xca , 0xfe ]) });
122+ const sigD = secp . sign (msgHash , priv , { lowS: false }); // malleable sig
122123```
123124
124- Generates low-s deterministic-k RFC6979 ECDSA signature. Assumes hash of message,
125+ Generates low-s deterministic-k RFC6979 ECDSA signature. Requries hash of message,
125126which means you'll need to do something like ` sha256(message) ` before signing.
126127
127- 1 . ` lowS: false ` allows to create malleable signatures, for compatibility with openssl.
128- Default ` lowS: true ` prohibits signatures which have (sig.s >= CURVE.n/2n) and is compatible with BTC/ETH.
129- 2 . ` extraEntropy: true ` enables hedged signatures with improved protection against fault attacks
130- - Check out blog post
131- [ Deterministic signatures are not your friends ] ( https://paulmillr.com/posts/deterministic-signatures/ )
132- and [ spec draft ] ( https://datatracker.ietf.org/doc/draft-irtf-cfrg-det-sigs-with-noise/ )
133- - Follows section 3.6 of RFC6979:
134- - No disadvantage: if an entropy generator is broken, sigs would be the same
135- as they are without the option
128+ ` extraEntropy: true ` enables hedged signatures. They incorporate
129+ extra randomness into RFC6979 (described in section 3.6),
130+ to provide additional protection against fault attacks.
131+ Check out blog post [ Deterministic signatures are not your friends ] ( https://paulmillr.com/posts/deterministic-signatures/ ) .
132+ Even if their RNG is broken, they will fall back to determinism.
133+
134+ Default behavior ` lowS: true ` prohibits signatures which have (sig.s >= CURVE.n/2n) and is compatible with BTC/ETH.
135+ Setting ` lowS: false ` allows to create malleable signatures, which is default openssl behavior.
136+ Non-malleable signatures can still be successfully verified in openssl.
136137
137138### verify
138139
139140``` ts
140- function verify(
141- signature : Hex | Signature , // returned by the `sign` function
142- messageHash : Hex , // message hash (not message) that must be verified
143- publicKey : Hex , // public (not private) key
144- opts ? : { lowS: boolean } // optional params; { lowS: true } by default
145- ): boolean ;
141+ import * as secp from ' @noble/secp256k1' ;
142+ const hex = secp .etc .hexToBytes ;
143+ const sig = hex (
144+ ' ddc633c5b48a1a6725c31201892715dda3058350f7b444e89d32c33c90d9c9e218d7eaf02c2254e88c3b33d755394b08bcc7efd13df02338510b750b64572983'
145+ );
146+ const msgHash = hex (' 736403f76264eccc1b77ba58dc8fc690e76b2b1532ba82c736a60f3862082db3' );
147+ // const priv = 'd60937c2a1ece169888d4c48717dfcc0e1a7af915505823148cca11859210e9c';
148+ const pubKey = hex (' 020b6d70b68873ff8fd729adf5cf4bf45021b34236f991768249cba06b11136ec6' );
149+
150+ const isValid = secp .verify (sig , msgHash , pubKey );
151+
152+ // Variants
153+ const isValidLoose = secp .verify (sig , msgHash , pubKey , { lowS: false });
146154```
147155
148- Verifies ECDSA signature and ensures it has lowS (compatible with BTC/ETH).
149- ` lowS: false ` turns off malleability check, but makes it OpenSSL-compatible.
156+ Verifies ECDSA signature.
157+ Default behavior ` lowS: true ` prohibits malleable signatures which have (` sig.s >= CURVE.n/2n ` ) and
158+ is compatible with BTC / ETH.
159+ Setting ` lowS: false ` allows to create signatures, which is default openssl behavior.
150160
151161### getSharedSecret
152162
153163``` ts
154- function getSharedSecret(
155- privateKeyA : Uint8Array | string , // Alices's private key
156- publicKeyB : Uint8Array | string , // Bob's public key
157- isCompressed = true // optional arg. (default) true=33b key, false=65b.
158- ): Uint8Array ;
164+ import * as secp from ' @noble/secp256k1' ;
165+ const bobsPriv = secp .utils .randomPrivateKey ();
166+ const alicesPub = secp .getPublicKey (secp .utils .randomPrivateKey ());
167+
168+ // ECDH between Alice and Bob
169+ const shared33b = secp .getSharedSecret (bobsPriv , alicesPub );
170+ const shared65b = secp .getSharedSecret (bobsPriv , alicesPub , false );
171+ const sharedPoint = secp .ProjectivePoint .fromHex (alicesPub ).multiply (bobsPriv );
159172```
160173
161174Computes ECDH (Elliptic Curve Diffie-Hellman) shared secret between
162175key A and different key B.
163176
164- Use ` ProjectivePoint.fromHex(publicKeyB).multiply(privateKeyA) ` for Point instance
165-
166177### recoverPublicKey
167178
168179``` ts
169- signature .recoverPublicKey (
170- msgHash : Uint8Array | string
171- ): Uint8Array | undefined ;
180+ import * as secp from ' @noble/secp256k1' ;
181+
182+ import { sha256 } from ' @noble/hashes/sha256' ;
183+ import { utf8ToBytes } from ' @noble/hashes/utils' ;
184+ const msg = ' noble cryptography' ;
185+ const msgHash = sha256 (utf8ToBytes (msg ));
186+ const priv = secp .utils .randomPrivateKey ();
187+ const pub1 = secp .getPubkicKey (priv );
188+ const sig = secp .sign (msgHash , priv );
189+
190+ const pub2 = sig .recoverPublicKey (msgHash );
172191```
173192
174193Recover public key from Signature instance with ` recovery ` bit set.
0 commit comments