@@ -93,4 +93,146 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms
9393
9494const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_function_bip340 ;
9595
96+ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying
97+ * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */
98+ static void secp256k1_schnorrsig_sha256_tagged (secp256k1_sha256 * sha ) {
99+ secp256k1_sha256_initialize (sha );
100+ sha -> s [0 ] = 0x9cecba11ul ;
101+ sha -> s [1 ] = 0x23925381ul ;
102+ sha -> s [2 ] = 0x11679112ul ;
103+ sha -> s [3 ] = 0xd1627e0ful ;
104+ sha -> s [4 ] = 0x97c87550ul ;
105+ sha -> s [5 ] = 0x003cc765ul ;
106+ sha -> s [6 ] = 0x90f61164ul ;
107+ sha -> s [7 ] = 0x33e9b66aul ;
108+ sha -> bytes = 64 ;
109+ }
110+
111+ int secp256k1_schnorrsig_sign (const secp256k1_context * ctx , unsigned char * sig64 , const unsigned char * msg32 , const secp256k1_keypair * keypair , secp256k1_nonce_function_hardened noncefp , void * ndata ) {
112+ secp256k1_scalar sk ;
113+ secp256k1_scalar e ;
114+ secp256k1_scalar k ;
115+ secp256k1_gej rj ;
116+ secp256k1_ge pk ;
117+ secp256k1_ge r ;
118+ secp256k1_sha256 sha ;
119+ unsigned char buf [32 ] = { 0 };
120+ unsigned char pk_buf [32 ];
121+ unsigned char seckey [32 ];
122+ int ret = 1 ;
123+
124+ VERIFY_CHECK (ctx != NULL );
125+ ARG_CHECK (secp256k1_ecmult_gen_context_is_built (& ctx -> ecmult_gen_ctx ));
126+ ARG_CHECK (sig64 != NULL );
127+ ARG_CHECK (msg32 != NULL );
128+ ARG_CHECK (keypair != NULL );
129+
130+ if (noncefp == NULL ) {
131+ noncefp = secp256k1_nonce_function_bip340 ;
132+ }
133+
134+ ret &= secp256k1_keypair_load (ctx , & sk , & pk , keypair );
135+ /* Because we are signing for a x-only pubkey, the secret key is negated
136+ * before signing if the point corresponding to the secret key does not
137+ * have an even Y. */
138+ if (secp256k1_fe_is_odd (& pk .y )) {
139+ secp256k1_scalar_negate (& sk , & sk );
140+ }
141+
142+ secp256k1_scalar_get_b32 (seckey , & sk );
143+ secp256k1_fe_get_b32 (pk_buf , & pk .x );
144+ ret &= !!noncefp (buf , msg32 , seckey , pk_buf , bip340_algo16 , ndata );
145+ secp256k1_scalar_set_b32 (& k , buf , NULL );
146+ ret &= !secp256k1_scalar_is_zero (& k );
147+ secp256k1_scalar_cmov (& k , & secp256k1_scalar_one , !ret );
148+
149+ secp256k1_ecmult_gen (& ctx -> ecmult_gen_ctx , & rj , & k );
150+ secp256k1_ge_set_gej (& r , & rj );
151+
152+ /* We declassify r to allow using it as a branch point. This is fine
153+ * because r is not a secret. */
154+ secp256k1_declassify (ctx , & r , sizeof (r ));
155+ secp256k1_fe_normalize_var (& r .y );
156+ if (secp256k1_fe_is_odd (& r .y )) {
157+ secp256k1_scalar_negate (& k , & k );
158+ }
159+ secp256k1_fe_normalize_var (& r .x );
160+ secp256k1_fe_get_b32 (& sig64 [0 ], & r .x );
161+
162+ /* tagged hash(r.x, pk.x, msg32) */
163+ secp256k1_schnorrsig_sha256_tagged (& sha );
164+ secp256k1_sha256_write (& sha , & sig64 [0 ], 32 );
165+ secp256k1_sha256_write (& sha , pk_buf , sizeof (pk_buf ));
166+ secp256k1_sha256_write (& sha , msg32 , 32 );
167+ secp256k1_sha256_finalize (& sha , buf );
168+
169+ /* Set scalar e to the challenge hash modulo the curve order as per
170+ * BIP340. */
171+ secp256k1_scalar_set_b32 (& e , buf , NULL );
172+ secp256k1_scalar_mul (& e , & e , & sk );
173+ secp256k1_scalar_add (& e , & e , & k );
174+ secp256k1_scalar_get_b32 (& sig64 [32 ], & e );
175+
176+ memczero (sig64 , 64 , !ret );
177+ secp256k1_scalar_clear (& k );
178+ secp256k1_scalar_clear (& sk );
179+ memset (seckey , 0 , sizeof (seckey ));
180+
181+ return ret ;
182+ }
183+
184+ int secp256k1_schnorrsig_verify (const secp256k1_context * ctx , const unsigned char * sig64 , const unsigned char * msg32 , const secp256k1_xonly_pubkey * pubkey ) {
185+ secp256k1_scalar s ;
186+ secp256k1_scalar e ;
187+ secp256k1_gej rj ;
188+ secp256k1_ge pk ;
189+ secp256k1_gej pkj ;
190+ secp256k1_fe rx ;
191+ secp256k1_ge r ;
192+ secp256k1_sha256 sha ;
193+ unsigned char buf [32 ];
194+ int overflow ;
195+
196+ VERIFY_CHECK (ctx != NULL );
197+ ARG_CHECK (secp256k1_ecmult_context_is_built (& ctx -> ecmult_ctx ));
198+ ARG_CHECK (sig64 != NULL );
199+ ARG_CHECK (msg32 != NULL );
200+ ARG_CHECK (pubkey != NULL );
201+
202+ if (!secp256k1_fe_set_b32 (& rx , & sig64 [0 ])) {
203+ return 0 ;
204+ }
205+
206+ secp256k1_scalar_set_b32 (& s , & sig64 [32 ], & overflow );
207+ if (overflow ) {
208+ return 0 ;
209+ }
210+
211+ if (!secp256k1_xonly_pubkey_load (ctx , & pk , pubkey )) {
212+ return 0 ;
213+ }
214+
215+ secp256k1_schnorrsig_sha256_tagged (& sha );
216+ secp256k1_sha256_write (& sha , & sig64 [0 ], 32 );
217+ secp256k1_fe_get_b32 (buf , & pk .x );
218+ secp256k1_sha256_write (& sha , buf , sizeof (buf ));
219+ secp256k1_sha256_write (& sha , msg32 , 32 );
220+ secp256k1_sha256_finalize (& sha , buf );
221+ secp256k1_scalar_set_b32 (& e , buf , NULL );
222+
223+ /* Compute rj = s*G + (-e)*pkj */
224+ secp256k1_scalar_negate (& e , & e );
225+ secp256k1_gej_set_ge (& pkj , & pk );
226+ secp256k1_ecmult (& ctx -> ecmult_ctx , & rj , & pkj , & e , & s );
227+
228+ secp256k1_ge_set_gej_var (& r , & rj );
229+ if (secp256k1_ge_is_infinity (& r )) {
230+ return 0 ;
231+ }
232+
233+ secp256k1_fe_normalize_var (& r .y );
234+ return !secp256k1_fe_is_odd (& r .y ) &&
235+ secp256k1_fe_equal_var (& rx , & r .x );
236+ }
237+
96238#endif
0 commit comments