118 const secp256k1_context* ctx,
119 unsigned char* proof_out,
120 const secp256k1_pubkey* R1,
const secp256k1_pubkey* S1,
const secp256k1_pubkey* P1,
121 const secp256k1_pubkey* R2,
const secp256k1_pubkey* S2,
const secp256k1_pubkey* P2,
123 const unsigned char* randomness_r1,
124 const unsigned char* randomness_r2,
125 const unsigned char* tx_context_id
127 unsigned char k_m[32], k_r1[32], k_r2[32];
128 unsigned char m_scalar[32] = {0};
130 unsigned char s_m[32], s_r1[32], s_r2[32];
131 unsigned char term[32];
132 secp256k1_pubkey T_m, T_r1_G, T_r1_P1, T_r2_G, T_r2_P2;
142 if (!secp256k1_ec_pubkey_create(ctx, &T_m, k_m))
goto cleanup;
144 if (!secp256k1_ec_pubkey_create(ctx, &T_r1_G, k_r1))
goto cleanup;
146 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &T_r1_P1, k_r1))
goto cleanup;
148 if (!secp256k1_ec_pubkey_create(ctx, &T_r2_G, k_r2))
goto cleanup;
150 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &T_r2_P2, k_r2))
goto cleanup;
154 &T_m, &T_r1_G, &T_r1_P1, &T_r2_G, &T_r2_P2,
158 for (
int i = 0; i < 8; ++i) m_scalar[31 - i] = (amount_m >> (i * 8)) & 0xFF;
161 memcpy(s_m, k_m, 32);
162 memcpy(term, m_scalar, 32);
163 if (!secp256k1_ec_seckey_tweak_mul(ctx, term, e))
goto cleanup;
164 if (!secp256k1_ec_seckey_tweak_add(ctx, s_m, term))
goto cleanup;
167 memcpy(s_r1, k_r1, 32);
168 memcpy(term, randomness_r1, 32);
169 if (!secp256k1_ec_seckey_tweak_mul(ctx, term, e))
goto cleanup;
170 if (!secp256k1_ec_seckey_tweak_add(ctx, s_r1, term))
goto cleanup;
173 memcpy(s_r2, k_r2, 32);
174 memcpy(term, randomness_r2, 32);
175 if (!secp256k1_ec_seckey_tweak_mul(ctx, term, e))
goto cleanup;
176 if (!secp256k1_ec_seckey_tweak_add(ctx, s_r2, term))
goto cleanup;
179 unsigned char* ptr = proof_out;
181 len = 33;
if(!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &T_m, SECP256K1_EC_COMPRESSED))
goto cleanup; ptr += 33;
182 len = 33;
if(!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &T_r1_G, SECP256K1_EC_COMPRESSED))
goto cleanup; ptr += 33;
183 len = 33;
if(!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &T_r1_P1, SECP256K1_EC_COMPRESSED))
goto cleanup; ptr += 33;
184 len = 33;
if(!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &T_r2_G, SECP256K1_EC_COMPRESSED))
goto cleanup; ptr += 33;
185 len = 33;
if(!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &T_r2_P2, SECP256K1_EC_COMPRESSED))
goto cleanup; ptr += 33;
187 memcpy(ptr, s_m, 32); ptr += 32;
188 memcpy(ptr, s_r1, 32); ptr += 32;
189 memcpy(ptr, s_r2, 32); ptr += 32;
194 OPENSSL_cleanse(k_m, 32);
195 OPENSSL_cleanse(k_r1, 32);
196 OPENSSL_cleanse(k_r2, 32);
197 OPENSSL_cleanse(m_scalar, 32);
202 const secp256k1_context* ctx,
203 const unsigned char* proof,
204 const secp256k1_pubkey* R1,
const secp256k1_pubkey* S1,
const secp256k1_pubkey* P1,
205 const secp256k1_pubkey* R2,
const secp256k1_pubkey* S2,
const secp256k1_pubkey* P2,
206 const unsigned char* tx_context_id
210 secp256k1_pubkey T_m, T_r1_G, T_r1_P1, T_r2_G, T_r2_P2;
211 unsigned char s_m[32], s_r1[32], s_r2[32];
213 const unsigned char* ptr = proof;
216 secp256k1_pubkey LHS, RHS, term, SmG;
217 const secp256k1_pubkey* pts[3];
222 if (!secp256k1_ec_pubkey_parse(ctx, &T_m, ptr, 33))
goto cleanup; ptr += 33;
223 if (!secp256k1_ec_pubkey_parse(ctx, &T_r1_G, ptr, 33))
goto cleanup; ptr += 33;
224 if (!secp256k1_ec_pubkey_parse(ctx, &T_r1_P1,ptr, 33))
goto cleanup; ptr += 33;
225 if (!secp256k1_ec_pubkey_parse(ctx, &T_r2_G, ptr, 33))
goto cleanup; ptr += 33;
226 if (!secp256k1_ec_pubkey_parse(ctx, &T_r2_P2,ptr, 33))
goto cleanup; ptr += 33;
229 memcpy(s_m, ptr, 32); ptr += 32;
230 memcpy(s_r1, ptr, 32); ptr += 32;
231 memcpy(s_r2, ptr, 32); ptr += 32;
234 if (!secp256k1_ec_seckey_verify(ctx, s_m))
goto cleanup;
235 if (!secp256k1_ec_seckey_verify(ctx, s_r1))
goto cleanup;
236 if (!secp256k1_ec_seckey_verify(ctx, s_r2))
goto cleanup;
240 &T_m, &T_r1_G, &T_r1_P1, &T_r2_G, &T_r2_P2,
246 if (!secp256k1_ec_pubkey_create(ctx, &SmG, s_m))
goto cleanup;
249 if (!secp256k1_ec_pubkey_create(ctx, &LHS, s_r1))
goto cleanup;
251 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, e))
goto cleanup;
252 pts[0] = &T_r1_G; pts[1] = &term;
253 if (!secp256k1_ec_pubkey_combine(ctx, &RHS, pts, 2))
goto cleanup;
258 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, s_r1))
goto cleanup;
259 pts[0] = &SmG; pts[1] = &term;
260 if (!secp256k1_ec_pubkey_combine(ctx, &LHS, pts, 2))
goto cleanup;
263 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, e))
goto cleanup;
264 pts[0] = &T_m; pts[1] = &T_r1_P1; pts[2] = &term;
265 if (!secp256k1_ec_pubkey_combine(ctx, &RHS, pts, 3))
goto cleanup;
269 if (!secp256k1_ec_pubkey_create(ctx, &LHS, s_r2))
goto cleanup;
271 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, e))
goto cleanup;
272 pts[0] = &T_r2_G; pts[1] = &term;
273 if (!secp256k1_ec_pubkey_combine(ctx, &RHS, pts, 2))
goto cleanup;
278 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, s_r2))
goto cleanup;
279 pts[0] = &SmG; pts[1] = &term;
280 if (!secp256k1_ec_pubkey_combine(ctx, &LHS, pts, 2))
goto cleanup;
283 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, e))
goto cleanup;
284 pts[0] = &T_m; pts[1] = &T_r2_P2; pts[2] = &term;
285 if (!secp256k1_ec_pubkey_combine(ctx, &RHS, pts, 3))
goto cleanup;
static void build_same_plaintext_hash_input(const secp256k1_context *ctx, unsigned char *e_out, const secp256k1_pubkey *R1, const secp256k1_pubkey *S1, const secp256k1_pubkey *P1, const secp256k1_pubkey *R2, const secp256k1_pubkey *S2, const secp256k1_pubkey *P2, const secp256k1_pubkey *T_m, const secp256k1_pubkey *T_r1_G, const secp256k1_pubkey *T_r1_P1, const secp256k1_pubkey *T_r2_G, const secp256k1_pubkey *T_r2_P2, const unsigned char *tx_context_id)
int secp256k1_mpt_prove_same_plaintext(const secp256k1_context *ctx, unsigned char *proof_out, const secp256k1_pubkey *R1, const secp256k1_pubkey *S1, const secp256k1_pubkey *P1, const secp256k1_pubkey *R2, const secp256k1_pubkey *S2, const secp256k1_pubkey *P2, uint64_t amount_m, const unsigned char *randomness_r1, const unsigned char *randomness_r2, const unsigned char *tx_context_id)
Generates a proof that two ciphertexts (under different keys) encrypt the same secret amount 'm'.
int secp256k1_mpt_verify_same_plaintext(const secp256k1_context *ctx, const unsigned char *proof, const secp256k1_pubkey *R1, const secp256k1_pubkey *S1, const secp256k1_pubkey *P1, const secp256k1_pubkey *R2, const secp256k1_pubkey *S2, const secp256k1_pubkey *P2, const unsigned char *tx_context_id)
Verifies a proof that two ciphertexts encrypt the same secret amount.
static int pubkey_equal(const secp256k1_context *ctx, const secp256k1_pubkey *pk1, const secp256k1_pubkey *pk2)
static int generate_random_scalar(const secp256k1_context *ctx, unsigned char *scalar)