109 const secp256k1_context* ctx,
110 unsigned char* proof,
111 const secp256k1_pubkey* c1,
112 const secp256k1_pubkey* c2,
113 const secp256k1_pubkey* pk,
114 const secp256k1_pubkey* pcm,
116 const unsigned char* r,
117 const unsigned char* rho,
118 const unsigned char* context_id)
120 unsigned char km[32], kr[32], krho[32];
122 unsigned char sm[32], sr[32], srho[32];
123 unsigned char term[32];
124 unsigned char m_scalar[32] = {0};
126 secp256k1_pubkey T1, T2, T3;
127 secp256k1_pubkey H, mG;
132 if (!secp256k1_ec_seckey_verify(ctx, r))
return 0;
133 if (!secp256k1_ec_seckey_verify(ctx, rho))
return 0;
143 if (!secp256k1_ec_pubkey_create(ctx, &T1, kr))
goto cleanup;
146 if (!secp256k1_ec_pubkey_create(ctx, &mG, km))
goto cleanup;
147 secp256k1_pubkey krPk = *pk;
148 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &krPk, kr))
goto cleanup;
149 const secp256k1_pubkey* add_t2[2] = {&mG, &krPk};
150 if (!secp256k1_ec_pubkey_combine(ctx, &T2, add_t2, 2))
goto cleanup;
155 secp256k1_pubkey krhoH = H;
156 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &krhoH, krho))
goto cleanup;
157 const secp256k1_pubkey* add_t3[2] = {&mG, &krhoH};
158 if (!secp256k1_ec_pubkey_combine(ctx, &T3, add_t3, 2))
goto cleanup;
165 for (
int i = 0; i < 8; i++) m_scalar[31 - i] = (amount >> (i * 8)) & 0xFF;
169 memcpy(term, m_scalar, 32);
170 if (!secp256k1_ec_seckey_tweak_mul(ctx, term, e))
goto cleanup;
171 if (!secp256k1_ec_seckey_tweak_add(ctx, sm, term))
goto cleanup;
176 if (!secp256k1_ec_seckey_tweak_mul(ctx, term, e))
goto cleanup;
177 if (!secp256k1_ec_seckey_tweak_add(ctx, sr, term))
goto cleanup;
180 memcpy(srho, krho, 32);
181 memcpy(term, rho, 32);
182 if (!secp256k1_ec_seckey_tweak_mul(ctx, term, e))
goto cleanup;
183 if (!secp256k1_ec_seckey_tweak_add(ctx, srho, term))
goto cleanup;
186 unsigned char* ptr = proof;
187 len = 33;
if (!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &T1, SECP256K1_EC_COMPRESSED))
goto cleanup; ptr += 33;
188 len = 33;
if (!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &T2, SECP256K1_EC_COMPRESSED))
goto cleanup; ptr += 33;
189 len = 33;
if (!secp256k1_ec_pubkey_serialize(ctx, ptr, &len, &T3, SECP256K1_EC_COMPRESSED))
goto cleanup; ptr += 33;
191 memcpy(ptr, sm, 32); ptr += 32;
192 memcpy(ptr, sr, 32); ptr += 32;
193 memcpy(ptr, srho, 32); ptr += 32;
199 OPENSSL_cleanse(km, 32);
200 OPENSSL_cleanse(kr, 32);
201 OPENSSL_cleanse(krho, 32);
202 OPENSSL_cleanse(m_scalar, 32);
203 OPENSSL_cleanse(term, 32);
204 OPENSSL_cleanse(sm, 32);
205 OPENSSL_cleanse(sr, 32);
206 OPENSSL_cleanse(srho, 32);
213 const secp256k1_context* ctx,
214 const unsigned char* proof,
215 const secp256k1_pubkey* c1,
216 const secp256k1_pubkey* c2,
217 const secp256k1_pubkey* pk,
218 const secp256k1_pubkey* pcm,
219 const unsigned char* context_id)
221 secp256k1_pubkey T1, T2, T3;
222 secp256k1_pubkey LHS, RHS, term, mG, H;
223 const secp256k1_pubkey* pts[2];
224 unsigned char sm[32], sr[32], srho[32], e[32];
225 const unsigned char* ptr = proof;
229 if (!secp256k1_ec_pubkey_parse(ctx, &T1, ptr, 33))
goto cleanup; ptr += 33;
230 if (!secp256k1_ec_pubkey_parse(ctx, &T2, ptr, 33))
goto cleanup; ptr += 33;
231 if (!secp256k1_ec_pubkey_parse(ctx, &T3, ptr, 33))
goto cleanup; ptr += 33;
233 memcpy(sm, ptr, 32); ptr += 32;
234 memcpy(sr, ptr, 32); ptr += 32;
235 memcpy(srho, ptr, 32); ptr += 32;
238 if (!secp256k1_ec_seckey_verify(ctx, sm))
goto cleanup;
239 if (!secp256k1_ec_seckey_verify(ctx, sr))
goto cleanup;
240 if (!secp256k1_ec_seckey_verify(ctx, srho))
goto cleanup;
249 if (!secp256k1_ec_pubkey_create(ctx, &LHS, sr))
goto cleanup;
252 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, e))
goto cleanup;
253 pts[0] = &T1; pts[1] = &term;
254 if (!secp256k1_ec_pubkey_combine(ctx, &RHS, pts, 2))
goto cleanup;
262 if (!secp256k1_ec_pubkey_create(ctx, &mG, sm))
goto cleanup;
265 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, sr))
goto cleanup;
267 pts[0] = &mG; pts[1] = &term;
268 if (!secp256k1_ec_pubkey_combine(ctx, &LHS, pts, 2))
goto cleanup;
272 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, e))
goto cleanup;
274 pts[0] = &T2; pts[1] = &term;
275 if (!secp256k1_ec_pubkey_combine(ctx, &RHS, pts, 2))
goto cleanup;
286 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, srho))
goto cleanup;
288 pts[0] = &mG; pts[1] = &term;
289 if (!secp256k1_ec_pubkey_combine(ctx, &LHS, pts, 2))
goto cleanup;
293 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &term, e))
goto cleanup;
295 pts[0] = &T3; pts[1] = &term;
296 if (!secp256k1_ec_pubkey_combine(ctx, &RHS, pts, 2))
goto cleanup;
static void build_link_challenge_hash(const secp256k1_context *ctx, unsigned char *e_out, const secp256k1_pubkey *c1, const secp256k1_pubkey *c2, const secp256k1_pubkey *pk, const secp256k1_pubkey *pcm, const secp256k1_pubkey *T1, const secp256k1_pubkey *T2, const secp256k1_pubkey *T3, const unsigned char *context_id)
int secp256k1_elgamal_pedersen_link_prove(const secp256k1_context *ctx, unsigned char *proof, const secp256k1_pubkey *c1, const secp256k1_pubkey *c2, const secp256k1_pubkey *pk, const secp256k1_pubkey *pcm, uint64_t amount, const unsigned char *r, const unsigned char *rho, const unsigned char *context_id)
Proves the link between an ElGamal ciphertext and a Pedersen commitment.
int secp256k1_elgamal_pedersen_link_verify(const secp256k1_context *ctx, const unsigned char *proof, const secp256k1_pubkey *c1, const secp256k1_pubkey *c2, const secp256k1_pubkey *pk, const secp256k1_pubkey *pcm, const unsigned char *context_id)
Verifies the link proof between ElGamal and Pedersen commitments.