70 const secp256k1_context* ctx,
73 const secp256k1_pubkey* C1,
74 const secp256k1_pubkey* C2_vec,
75 const secp256k1_pubkey* Pk_vec,
76 const secp256k1_pubkey* Tr,
77 const secp256k1_pubkey* Tm_vec,
78 const unsigned char* context_id
81 unsigned char buf[33];
85 const char* domain =
"MPT_POK_SAME_PLAINTEXT_SHARED_R";
88 SHA256_Update(&sha, domain, strlen(domain));
91 len = 33; secp256k1_ec_pubkey_serialize(ctx, buf, &len, C1, SECP256K1_EC_COMPRESSED);
92 SHA256_Update(&sha, buf, 33);
95 for (i = 0; i < n; i++) {
96 len = 33; secp256k1_ec_pubkey_serialize(ctx, buf, &len, &C2_vec[i], SECP256K1_EC_COMPRESSED);
97 SHA256_Update(&sha, buf, 33);
98 len = 33; secp256k1_ec_pubkey_serialize(ctx, buf, &len, &Pk_vec[i], SECP256K1_EC_COMPRESSED);
99 SHA256_Update(&sha, buf, 33);
103 len = 33; secp256k1_ec_pubkey_serialize(ctx, buf, &len, Tr, SECP256K1_EC_COMPRESSED);
104 SHA256_Update(&sha, buf, 33);
107 for (i = 0; i < n; i++) {
108 len = 33; secp256k1_ec_pubkey_serialize(ctx, buf, &len, &Tm_vec[i], SECP256K1_EC_COMPRESSED);
109 SHA256_Update(&sha, buf, 33);
114 SHA256_Update(&sha, context_id, 32);
117 SHA256_Final(h, &sha);
124 const secp256k1_context* ctx,
125 unsigned char* proof_out,
127 const unsigned char* r_shared,
129 const secp256k1_pubkey* C1,
130 const secp256k1_pubkey* C2_vec,
131 const secp256k1_pubkey* Pk_vec,
132 const unsigned char* context_id
135 unsigned char k_m[32], k_r[32];
136 unsigned char m_scalar[32] = {0};
138 unsigned char s_m[32], s_r[32];
139 unsigned char term[32];
142 secp256k1_pubkey* Tm_vec = NULL;
145 unsigned char* ptr = proof_out;
149 if (!secp256k1_ec_seckey_verify(ctx, r_shared))
return 0;
153 Tm_vec = (secp256k1_pubkey*)malloc(
sizeof(secp256k1_pubkey) * n);
154 if (!Tm_vec)
return 0;
158 for (i = 0; i < 8; i++) {
159 m_scalar[31 - i] = (amount >> (i * 8)) & 0xFF;
169 if (!secp256k1_ec_pubkey_create(ctx, &Tr, k_r))
goto cleanup;
172 secp256k1_pubkey kmG;
173 if (!secp256k1_ec_pubkey_create(ctx, &kmG, k_m))
goto cleanup;
175 for (i = 0; i < n; i++) {
176 secp256k1_pubkey krPk = Pk_vec[i];
177 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &krPk, k_r))
goto cleanup;
179 const secp256k1_pubkey* pts[2] = {&kmG, &krPk};
180 if (!secp256k1_ec_pubkey_combine(ctx, &Tm_vec[i], pts, 2))
goto cleanup;
189 memcpy(s_m, k_m, 32);
190 memcpy(term, m_scalar, 32);
191 if (!secp256k1_ec_seckey_tweak_mul(ctx, term, e))
goto cleanup;
192 if (!secp256k1_ec_seckey_tweak_add(ctx, s_m, term))
goto cleanup;
195 memcpy(s_r, k_r, 32);
196 memcpy(term, r_shared, 32);
197 if (!secp256k1_ec_seckey_tweak_mul(ctx, term, e))
goto cleanup;
198 if (!secp256k1_ec_seckey_tweak_add(ctx, s_r, term))
goto cleanup;
204 if (!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &Tr, SECP256K1_EC_COMPRESSED))
goto cleanup;
208 for (i = 0; i < n; i++) {
210 if (!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &Tm_vec[i], SECP256K1_EC_COMPRESSED))
goto cleanup;
215 memcpy(ptr, s_m, 32); ptr += 32;
216 memcpy(ptr, s_r, 32); ptr += 32;
222 OPENSSL_cleanse(k_m, 32);
223 OPENSSL_cleanse(k_r, 32);
224 OPENSSL_cleanse(m_scalar, 32);
227 OPENSSL_cleanse(term, 32);
228 OPENSSL_cleanse(s_m, 32);
229 OPENSSL_cleanse(s_r, 32);
231 if (Tm_vec) free(Tm_vec);
235 const secp256k1_context* ctx,
236 const unsigned char* proof,
238 const secp256k1_pubkey* C1,
239 const secp256k1_pubkey* C2_vec,
240 const secp256k1_pubkey* Pk_vec,
241 const unsigned char* context_id
248 secp256k1_pubkey* Tm_vec = NULL;
249 unsigned char s_m[32], s_r[32];
253 const unsigned char* ptr = proof;
256 Tm_vec = (secp256k1_pubkey*)malloc(
sizeof(secp256k1_pubkey) * n);
257 if (!Tm_vec)
return 0;
262 if (!secp256k1_ec_pubkey_parse(ctx, &Tr, ptr, 33))
goto cleanup;
266 for (i = 0; i < n; i++) {
267 if (!secp256k1_ec_pubkey_parse(ctx, &Tm_vec[i], ptr, 33))
goto cleanup;
272 memcpy(s_m, ptr, 32); ptr += 32;
273 memcpy(s_r, ptr, 32); ptr += 32;
276 if (!secp256k1_ec_seckey_verify(ctx, s_m))
goto cleanup;
277 if (!secp256k1_ec_seckey_verify(ctx, s_r))
goto cleanup;
286 secp256k1_pubkey LHS, RHS;
287 secp256k1_pubkey eC1 = *C1;
289 if (!secp256k1_ec_pubkey_create(ctx, &LHS, s_r))
goto cleanup;
291 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &eC1, e))
goto cleanup;
292 const secp256k1_pubkey* pts[2] = {&Tr, &eC1};
293 if (!secp256k1_ec_pubkey_combine(ctx, &RHS, pts, 2))
goto cleanup;
300 secp256k1_pubkey smG;
301 if (!secp256k1_ec_pubkey_create(ctx, &smG, s_m))
goto cleanup;
303 for (i = 0; i < n; i++) {
304 secp256k1_pubkey LHS, RHS;
307 secp256k1_pubkey srPk = Pk_vec[i];
308 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &srPk, s_r))
goto cleanup;
310 const secp256k1_pubkey* lhs_pts[2] = {&smG, &srPk};
311 if (!secp256k1_ec_pubkey_combine(ctx, &LHS, lhs_pts, 2))
goto cleanup;
314 secp256k1_pubkey eC2 = C2_vec[i];
315 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &eC2, e))
goto cleanup;
317 const secp256k1_pubkey* rhs_pts[2] = {&Tm_vec[i], &eC2};
318 if (!secp256k1_ec_pubkey_combine(ctx, &RHS, rhs_pts, 2))
goto cleanup;
325 if ((
size_t)(ptr - proof) != expected_len)
goto cleanup;
330 if (Tm_vec) free(Tm_vec);
size_t secp256k1_mpt_proof_equality_shared_r_size(size_t n_recipients)
static void compute_challenge_equality_shared_r(const secp256k1_context *ctx, unsigned char *e_out, size_t n, const secp256k1_pubkey *C1, const secp256k1_pubkey *C2_vec, const secp256k1_pubkey *Pk_vec, const secp256k1_pubkey *Tr, const secp256k1_pubkey *Tm_vec, const unsigned char *context_id)
int secp256k1_mpt_prove_equality_shared_r(const secp256k1_context *ctx, unsigned char *proof_out, uint64_t amount, const unsigned char *r_shared, size_t n, const secp256k1_pubkey *C1, const secp256k1_pubkey *C2_vec, const secp256k1_pubkey *Pk_vec, const unsigned char *context_id)
static int pubkey_equal(const secp256k1_context *ctx, const secp256k1_pubkey *pk1, const secp256k1_pubkey *pk2)
int secp256k1_mpt_verify_equality_shared_r(const secp256k1_context *ctx, const unsigned char *proof, size_t n, const secp256k1_pubkey *C1, const secp256k1_pubkey *C2_vec, const secp256k1_pubkey *Pk_vec, const unsigned char *context_id)
static int generate_random_scalar(const secp256k1_context *ctx, unsigned char *scalar)