Skip to content

Commit b5ef01f

Browse files
committed
add secp256k1_silentpayments_create_shared_secret_with_proof
- add new internal function which returns both DLEQ proof and shared secret. - the existing secp256k1_silentpayments_create_shared_secret API is refactored to use secp256k1_silentpayments_create_shared_secret_with_proof.
1 parent 9948bf1 commit b5ef01f

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

src/modules/silentpayments/main_impl.h

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "../../../include/secp256k1.h"
1010
#include "../../../include/secp256k1_extrakeys.h"
1111
#include "../../../include/secp256k1_silentpayments.h"
12+
#include "dleq_impl.h"
1213

1314
/** Sort an array of silent payment recipients. This is used to group recipients by scan pubkey to
1415
* ensure the correct values of k are used when creating multiple outputs for a recipient. */
@@ -64,15 +65,46 @@ static void secp256k1_silentpayments_calculate_input_hash(unsigned char *input_h
6465
secp256k1_sha256_finalize(&hash, input_hash);
6566
}
6667

67-
static void secp256k1_silentpayments_create_shared_secret(unsigned char *shared_secret33, const secp256k1_scalar *secret_component, const secp256k1_ge *public_component) {
68+
static int secp256k1_silentpayments_create_shared_secret_with_proof(const secp256k1_context *ctx, unsigned char *proof64, secp256k1_ge *shared_secret, const secp256k1_scalar *secret_component, secp256k1_ge *public_component) {
6869
secp256k1_gej ss_j;
69-
secp256k1_ge ss;
70-
size_t len;
71-
int ret;
70+
int ret = 1;
7271

7372
/* Compute shared_secret = tweaked_secret_component * Public_component */
7473
secp256k1_ecmult_const(&ss_j, public_component, secret_component);
75-
secp256k1_ge_set_gej(&ss, &ss_j);
74+
secp256k1_ge_set_gej(shared_secret, &ss_j);
75+
76+
if (proof64 != NULL) {
77+
secp256k1_scalar s;
78+
secp256k1_scalar e;
79+
secp256k1_ge ge_secret_component;
80+
secp256k1_gej gej_secret_component;
81+
82+
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &gej_secret_component, secret_component);
83+
secp256k1_ge_set_gej(&ge_secret_component, &gej_secret_component);
84+
85+
ret &= secp256k1_dleq_prove(ctx, &s, &e, secret_component, public_component, &ge_secret_component, shared_secret,
86+
NULL, NULL); /*todo: how to pass auxrand*/
87+
/* sanity check*/
88+
ret &= secp256k1_dleq_verify(&s, &e, &ge_secret_component, public_component, shared_secret, NULL);
89+
90+
secp256k1_scalar_get_b32(proof64, &s);
91+
secp256k1_scalar_get_b32(proof64 + 32, &e);
92+
}
93+
/* While not technically "secret" data, explicitly clear the shared secret since leaking this would allow an attacker
94+
* to identify the resulting transaction as a silent payments transaction and potentially link the transaction
95+
* back to the silent payment address
96+
*/
97+
secp256k1_gej_clear(&ss_j);
98+
return ret;
99+
}
100+
101+
static void secp256k1_silentpayments_create_shared_secret(const secp256k1_context* ctx, unsigned char *shared_secret33, const secp256k1_scalar *secret_component, secp256k1_ge *public_component) {
102+
size_t len;
103+
int ret;
104+
secp256k1_ge ss;
105+
106+
ret = secp256k1_silentpayments_create_shared_secret_with_proof(ctx, NULL, &ss, secret_component, public_component);
107+
VERIFY_CHECK(ret);
76108
/* This can only fail if the shared secret is the point at infinity, which should be
77109
* impossible at this point, considering we have already validated the public key and
78110
* the secret key being used
@@ -85,7 +117,6 @@ static void secp256k1_silentpayments_create_shared_secret(unsigned char *shared_
85117
* back to the silent payment address
86118
*/
87119
secp256k1_ge_clear(&ss);
88-
secp256k1_gej_clear(&ss_j);
89120
}
90121

91122
/** Set hash state to the BIP340 tagged hash midstate for "BIP0352/SharedSecret". */
@@ -233,7 +264,7 @@ int secp256k1_silentpayments_sender_create_outputs(
233264
secp256k1_ge pk;
234265
ret &= secp256k1_pubkey_load(ctx, &pk, &recipients[i]->scan_pubkey);
235266
if (!ret) break;
236-
secp256k1_silentpayments_create_shared_secret(shared_secret, &a_sum_scalar, &pk);
267+
secp256k1_silentpayments_create_shared_secret(ctx, shared_secret, &a_sum_scalar, &pk);
237268
k = 0;
238269
}
239270
ret &= secp256k1_silentpayments_create_output_pubkey(ctx, generated_outputs[recipients[i]->index], shared_secret, &recipients[i]->spend_pubkey, k);
@@ -490,7 +521,7 @@ int secp256k1_silentpayments_recipient_scan_outputs(
490521
secp256k1_scalar_mul(&rsk_scalar, &rsk_scalar, &input_hash_scalar);
491522
ret &= !overflow;
492523
}
493-
secp256k1_silentpayments_create_shared_secret(shared_secret, &rsk_scalar, &A_sum_ge);
524+
secp256k1_silentpayments_create_shared_secret(ctx, shared_secret, &rsk_scalar, &A_sum_ge);
494525

495526
found_idx = 0;
496527
n_found = 0;
@@ -609,7 +640,7 @@ int secp256k1_silentpayments_recipient_create_shared_secret(const secp256k1_cont
609640
if (!ret) {
610641
return 0;
611642
}
612-
secp256k1_silentpayments_create_shared_secret(shared_secret33, &rsk, &A_tweaked_ge);
643+
secp256k1_silentpayments_create_shared_secret(ctx, shared_secret33, &rsk, &A_tweaked_ge);
613644

614645
/* Explicitly clear secrets */
615646
secp256k1_scalar_clear(&rsk);

0 commit comments

Comments
 (0)