Skip to content

Commit 03148a1

Browse files
committed
silentpayments: add shared secret creation routine for sender (a*B)
1 parent 759eb1f commit 03148a1

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

include/secp256k1_silentpayments.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define SECP256K1_SILENTPAYMENTS_H
33

44
#include "secp256k1.h"
5+
#include "secp256k1_extrakeys.h"
56

67
#ifdef __cplusplus
78
extern "C" {
@@ -61,6 +62,30 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_p
6162
const unsigned char *outpoints_hash32
6263
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(7);
6364

65+
/** Create Silent Payment shared secret for the sender side.
66+
*
67+
* Given private input tweak data a_tweaked a recipient's scan public key B_scan,
68+
* compute the corresponding shared secret using ECDH:
69+
*
70+
* shared_secret = a_tweaked * B_scan
71+
* (where a_tweaked = (a_0 + a_1 + ... a_(n-1)) * outpoints_hash)
72+
*
73+
* The resulting data is needed as input for creating silent payments outputs
74+
* belonging to the same receiver scan public key.
75+
*
76+
* Returns: 1 if shared secret creation was successful. 0 if an error occured.
77+
* Args: ctx: pointer to a context object
78+
* Out: shared_secret33: pointer to the resulting 33-byte shared secret
79+
* In: tweak_data32: pointer to 32-byte private input tweak data
80+
* receiver_scan_pubkey: pointer to the receiver's scan pubkey
81+
*/
82+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_send_create_shared_secret(
83+
const secp256k1_context *ctx,
84+
unsigned char *shared_secret33,
85+
const unsigned char *tweak_data32,
86+
const secp256k1_pubkey *receiver_scan_pubkey
87+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
88+
6489
/* TODO: add function API for receiver side. */
6590

6691
#ifdef __cplusplus

src/modules/silentpayments/main_impl.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,35 @@
77
#define SECP256K1_MODULE_SILENTPAYMENTS_MAIN_H
88

99
#include "../../../include/secp256k1.h"
10+
#include "../../../include/secp256k1_ecdh.h"
11+
#include "../../../include/secp256k1_extrakeys.h"
1012
#include "../../../include/secp256k1_silentpayments.h"
1113

14+
/* secp256k1_ecdh expects a hash function to be passed in or uses its default
15+
* hashing function. We don't want to hash the ECDH result, so we define a
16+
* custom function which simply returns the pubkey without hashing.
17+
*/
18+
static int ecdh_return_pubkey(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) {
19+
secp256k1_pubkey pubkey;
20+
unsigned char uncompressed_pubkey[65];
21+
size_t outputlen = 33;
22+
(void)data;
23+
24+
uncompressed_pubkey[0] = 0x04;
25+
memcpy(uncompressed_pubkey + 1, x32, 32);
26+
memcpy(uncompressed_pubkey + 33, y32, 32);
27+
28+
if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, uncompressed_pubkey, 65)) {
29+
return 0;
30+
}
31+
32+
if (!secp256k1_ec_pubkey_serialize(secp256k1_context_static, output, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED)) {
33+
return 0;
34+
}
35+
36+
return 1;
37+
}
38+
1239
int secp256k1_silentpayments_create_private_tweak_data(const secp256k1_context *ctx, unsigned char *tweak_data32, const unsigned char *plain_seckeys, size_t n_plain_seckeys, const unsigned char *taproot_seckeys, size_t n_taproot_seckeys, const unsigned char *outpoints_hash32) {
1340
size_t i;
1441
unsigned char a_tweaked[32];
@@ -70,6 +97,20 @@ int secp256k1_silentpayments_create_private_tweak_data(const secp256k1_context *
7097
return 1;
7198
}
7299

100+
int secp256k1_silentpayments_send_create_shared_secret(const secp256k1_context *ctx, unsigned char *shared_secret33, const unsigned char *tweak_data32, const secp256k1_pubkey *receiver_scan_pubkey) {
101+
/* Sanity check inputs */
102+
ARG_CHECK(shared_secret33 != NULL);
103+
memset(shared_secret33, 0, 33);
104+
ARG_CHECK(receiver_scan_pubkey != NULL);
105+
106+
/* Compute shared_secret = a_tweaked * B_scan */
107+
if (!secp256k1_ecdh(ctx, shared_secret33, receiver_scan_pubkey, tweak_data32, ecdh_return_pubkey, NULL)) {
108+
return 0;
109+
}
110+
111+
return 1;
112+
}
113+
73114
/* TODO: implement functions for receiver side. */
74115

75116
#endif

0 commit comments

Comments
 (0)