Bitcoin ABC 0.32.6
P2P Digital Currency
schnorr_impl.h
Go to the documentation of this file.
1/***********************************************************************
2 * Copyright (c) 2017 Amaury SÉCHET *
3 * Distributed under the MIT software license, see the accompanying *
4 * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
5 ***********************************************************************/
6
7#ifndef SECP256K1_MODULE_SCHNORR_IMPL_H
8#define SECP256K1_MODULE_SCHNORR_IMPL_H
9
10#include <string.h>
11
12#include "schnorr.h"
13#include "field.h"
14#include "group.h"
15#include "hash.h"
16#include "ecmult.h"
17#include "ecmult_gen.h"
18
52 const unsigned char *sig64,
53 secp256k1_ge *pubkey,
54 const unsigned char *msg32
55) {
56 secp256k1_gej Pj, Rj;
57 secp256k1_fe Rx;
59 int overflow;
60
62
63 /* Extract s */
64 overflow = 0;
65 secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow);
66 if (overflow) {
67 return 0;
68 }
69
70 /* Extract R.x */
71 if (!secp256k1_fe_set_b32(&Rx, sig64)) {
72 return 0;
73 }
74
75 /* Compute e */
76 secp256k1_schnorr_compute_e(&e, sig64, pubkey, msg32);
77
78 /* Verify the signature */
80 secp256k1_gej_set_ge(&Pj, pubkey);
81 secp256k1_ecmult(&Rj, &Pj, &e, &s);
83 return 0;
84 }
85
86 /* Check that R.x is what we expect */
87 if (!secp256k1_gej_eq_x_var(&Rx, &Rj)) {
88 return 0;
89 }
90
91 /* Check that jacobi(R.y) is 1 */
93 return 0;
94 }
95
96 /* All good, we have a valid signature. */
97 return 1;
98}
99
102 const unsigned char *r,
103 secp256k1_ge *p,
104 const unsigned char *msg32
105) {
106 int overflow = 0;
107 size_t size = 0;
109 unsigned char buf[33];
111
112 /* R.x */
113 secp256k1_sha256_write(&sha, r, 32);
114
115 /* compressed P */
116 secp256k1_eckey_pubkey_serialize(p, buf, &size, 1);
117 VERIFY_CHECK(size == 33);
118 secp256k1_sha256_write(&sha, buf, 33);
119
120 /* msg */
121 secp256k1_sha256_write(&sha, msg32, 32);
122
123 /* compute e */
124 secp256k1_sha256_finalize(&sha, buf);
125 secp256k1_scalar_set_b32(e, buf, &overflow);
126 return !overflow & !secp256k1_scalar_is_zero(e);
127}
128
130 const secp256k1_context* ctx,
131 unsigned char *sig64,
132 const unsigned char *msg32,
133 const secp256k1_scalar *privkey,
134 secp256k1_ge *pubkey,
136 const void *ndata
137) {
138 secp256k1_ge R;
139 secp256k1_gej Rj;
140 secp256k1_scalar k, e, s;
142
145
146 if (!secp256k1_schnorr_sig_generate_k(ctx, &k, msg32, privkey, noncefp, ndata)) {
147 return 0;
148 }
149
150 /* Compute R */
152 secp256k1_ge_set_gej(&R, &Rj);
153
154 /*
155 * We declassify R to allow using it as a branch point.
156 * This is fine because R is not a secret.
157 */
158 secp256k1_declassify(ctx, &R, sizeof(R));
161
162 /* Compute the signature. */
164 secp256k1_fe_get_b32(sig64, &R.x);
165 secp256k1_schnorr_compute_e(&e, sig64, pubkey, msg32);
166 secp256k1_scalar_mul(&s, &e, privkey);
167 secp256k1_scalar_add(&s, &s, &k);
168 secp256k1_scalar_get_b32(sig64 + 32, &s);
169
170 /* Cleanup locals that may contain private data. */
172 return 1;
173}
174
176 const secp256k1_context* ctx,
178 const unsigned char *msg32,
179 const secp256k1_scalar *privkey,
181 const void *ndata
182) {
183 int ret = 0;
184 unsigned int count = 0;
185 unsigned char nonce32[32], seckey[32];
186
187 /* Seed used to make sure we generate different values of k for schnorr */
188 const unsigned char secp256k1_schnorr_algo16[17] = "Schnorr+SHA256 ";
189
190 if (noncefp == NULL) {
192 }
193
194 secp256k1_scalar_get_b32(seckey, privkey);
195 while (1) {
196 int overflow;
197 ret = noncefp(nonce32, msg32, seckey, secp256k1_schnorr_algo16, (void*)ndata, count++);
198 if (!ret) {
199 break;
200 }
201
202 secp256k1_scalar_set_b32(k, nonce32, &overflow);
203 overflow |= secp256k1_scalar_is_zero(k);
204 /* The nonce is still secret here, but it overflowing or being zero is is less likely than 1:2^255. */
205 secp256k1_declassify(ctx, &overflow, sizeof(overflow));
206 if (!overflow) {
207 break;
208 }
209
211 }
212
213 /* Cleanup locals that may contain private data. */
214 memset(seckey, 0, 32);
215 memset(nonce32, 0, 32);
216 return ret;
217}
218
219#endif
secp256k1_context * ctx
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed)
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng)
Double multiply: R = na*A + ng*G.
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *a)
Multiply with the generator: R = a*G.
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context *ctx)
static int secp256k1_fe_is_quad_var(const secp256k1_fe *a)
Checks whether a field element is a quadratic residue.
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a)
Set a field element equal to 32-byte big endian value.
static void secp256k1_fe_normalize(secp256k1_fe *r)
Field element module.
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a)
Convert a field element to a 32-byte big endian value.
static int secp256k1_gej_is_infinity(const secp256k1_gej *a)
Check whether a group element is the point at infinity.
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a)
Compare the X coordinate of a group element (jacobian).
static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a)
Set a group element equal to another which is given in jacobian coordinates.
static int secp256k1_ge_is_infinity(const secp256k1_ge *a)
Check whether a group element is the point at infinity.
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a)
Set a group element (jacobian) equal to another which is given in affine coordinates.
static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a)
Check whether a group element's y coordinate is a quadratic residue.
static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow)
Set a scalar from a big endian byte array.
static int secp256k1_scalar_is_zero(const secp256k1_scalar *a)
Check whether a scalar equals zero.
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar *a)
Convert a scalar to a byte array.
static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag)
Conditionally negate a number, in constant time.
static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b)
Add two scalars together (modulo the group order).
static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b)
Multiply two scalars (modulo the group order).
static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a)
Compute the complement of a scalar (modulo the group order).
static void secp256k1_scalar_clear(secp256k1_scalar *r)
Clear a scalar to prevent the leak of sensitive data.
static int secp256k1_schnorr_sig_verify(const unsigned char *sig64, secp256k1_ge *pubkey, const unsigned char *msg32)
Custom Schnorr-based signature scheme.
Definition: schnorr_impl.h:51
static int secp256k1_schnorr_compute_e(secp256k1_scalar *e, const unsigned char *r, secp256k1_ge *p, const unsigned char *msg32)
Definition: schnorr_impl.h:100
static int secp256k1_schnorr_sig_sign(const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_ge *pubkey, secp256k1_nonce_function noncefp, const void *ndata)
Definition: schnorr_impl.h:129
static int secp256k1_schnorr_sig_generate_k(const secp256k1_context *ctx, secp256k1_scalar *k, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_nonce_function noncefp, const void *ndata)
Definition: schnorr_impl.h:175
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash)
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32)
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size)
#define VERIFY_CHECK(cond)
Definition: util.h:68
#define ARG_CHECK(cond)
Definition: secp256k1.c:34
static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context *ctx, const void *p, size_t len)
Definition: secp256k1.c:227
SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_default
A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979).
Definition: secp256k1.c:494
int(* secp256k1_nonce_function)(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int attempt)
A pointer to a function to deterministically generate a nonce.
Definition: secp256k1.h:103
secp256k1_ecmult_gen_context ecmult_gen_ctx
Definition: secp256k1.c:76
A group element of the secp256k1 curve, in affine coordinates.
Definition: group.h:13
secp256k1_fe x
Definition: group.h:14
secp256k1_fe y
Definition: group.h:15
A group element of the secp256k1 curve, in jacobian coordinates.
Definition: group.h:23
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_4x64.h:13
static int count
Definition: tests.c:31