Skip to content

Commit 74351a1

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

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-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" {
@@ -64,6 +65,30 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_create_p
6465
const unsigned char *outpoint_smallest36
6566
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(7);
6667

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

6994
#ifdef __cplusplus

src/modules/silentpayments/main_impl.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
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

1214
/** Set hash state to the BIP340 tagged hash midstate for "BIP0352/Inputs". */
@@ -102,6 +104,46 @@ int secp256k1_silentpayments_create_private_tweak_data(const secp256k1_context *
102104
return 1;
103105
}
104106

107+
/* secp256k1_ecdh expects a hash function to be passed in or uses its default
108+
* hashing function. We don't want to hash the ECDH result, so we define a
109+
* custom function which simply returns the pubkey without hashing.
110+
*/
111+
static int secp256k1_silentpayments_ecdh_return_pubkey(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) {
112+
secp256k1_ge point;
113+
secp256k1_fe x, y;
114+
size_t ser_size;
115+
int ser_ret;
116+
117+
(void)data;
118+
/* Parse point as group element */
119+
if (!secp256k1_fe_set_b32_limit(&x, x32) || !secp256k1_fe_set_b32_limit(&y, y32)) {
120+
return 0;
121+
}
122+
secp256k1_ge_set_xy(&point, &x, &y);
123+
124+
/* Serialize as compressed pubkey */
125+
ser_ret = secp256k1_eckey_pubkey_serialize(&point, output, &ser_size, 1);
126+
VERIFY_CHECK(ser_ret && ser_size == 33);
127+
(void)ser_ret;
128+
129+
return 1;
130+
}
131+
132+
int secp256k1_silentpayments_send_create_shared_secret(const secp256k1_context *ctx, unsigned char *shared_secret33, const unsigned char *private_tweak_data32, const secp256k1_pubkey *receiver_scan_pubkey) {
133+
/* Sanity check inputs */
134+
ARG_CHECK(shared_secret33 != NULL);
135+
memset(shared_secret33, 0, 33);
136+
ARG_CHECK(private_tweak_data32 != NULL);
137+
ARG_CHECK(receiver_scan_pubkey != NULL);
138+
139+
/* Compute shared_secret = a_tweaked * B_scan */
140+
if (!secp256k1_ecdh(ctx, shared_secret33, receiver_scan_pubkey, private_tweak_data32, secp256k1_silentpayments_ecdh_return_pubkey, NULL)) {
141+
return 0;
142+
}
143+
144+
return 1;
145+
}
146+
105147
/* TODO: implement functions for receiver side. */
106148

107149
#endif

0 commit comments

Comments
 (0)