Skip to content

Commit 39c0939

Browse files
theStackjosibake
authored andcommitted
silentpayments: implement shared secret creation
Add function for calculating either a*B or A*b. This function is used by both the sender and the recipient (i.e. a*B == A*b). Add functions for generating the tagged input hash, as this is used when creating the shared secret. In a later commit, `create_shared_secret` will be exposed in the API for the receiver to use when scanning as a light client.
1 parent 62b6cd0 commit 39c0939

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

src/modules/silentpayments/main_impl.h

Lines changed: 82 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
/** Sort an array of silent payment recipients. This is used to group recipients by scan pubkey to
@@ -41,4 +43,84 @@ int secp256k1_silentpayments_recipient_sort(const secp256k1_context* ctx, const
4143
return 1;
4244
}
4345

46+
/** Set hash state to the BIP340 tagged hash midstate for "BIP0352/Inputs". */
47+
static void secp256k1_silentpayments_sha256_init_inputs(secp256k1_sha256* hash) {
48+
secp256k1_sha256_initialize(hash);
49+
hash->s[0] = 0xd4143ffcul;
50+
hash->s[1] = 0x012ea4b5ul;
51+
hash->s[2] = 0x36e21c8ful;
52+
hash->s[3] = 0xf7ec7b54ul;
53+
hash->s[4] = 0x4dd4e2acul;
54+
hash->s[5] = 0x9bcaa0a4ul;
55+
hash->s[6] = 0xe244899bul;
56+
hash->s[7] = 0xcd06903eul;
57+
58+
hash->bytes = 64;
59+
}
60+
61+
static void secp256k1_silentpayments_calculate_input_hash(unsigned char *input_hash, const unsigned char *outpoint_smallest36, secp256k1_ge *pubkey_sum) {
62+
secp256k1_sha256 hash;
63+
unsigned char pubkey_sum_ser[33];
64+
size_t ser_size;
65+
int ser_ret;
66+
67+
secp256k1_silentpayments_sha256_init_inputs(&hash);
68+
secp256k1_sha256_write(&hash, outpoint_smallest36, 36);
69+
ser_ret = secp256k1_eckey_pubkey_serialize(pubkey_sum, pubkey_sum_ser, &ser_size, 1);
70+
VERIFY_CHECK(ser_ret && ser_size == sizeof(pubkey_sum_ser));
71+
(void)ser_ret;
72+
secp256k1_sha256_write(&hash, pubkey_sum_ser, sizeof(pubkey_sum_ser));
73+
secp256k1_sha256_finalize(&hash, input_hash);
74+
}
75+
76+
/* secp256k1_ecdh expects a hash function to be passed in or uses its default
77+
* hashing function. We don't want to hash the ECDH result yet (it will be
78+
* hashed later with a counter `k`), so we define a custom function which simply
79+
* returns the pubkey without hashing.
80+
*/
81+
static int secp256k1_silentpayments_ecdh_return_pubkey(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) {
82+
secp256k1_ge point;
83+
secp256k1_fe x, y;
84+
size_t ser_size;
85+
int ser_ret;
86+
87+
(void)data;
88+
/* Parse point as group element */
89+
if (!secp256k1_fe_set_b32_limit(&x, x32) || !secp256k1_fe_set_b32_limit(&y, y32)) {
90+
return 0;
91+
}
92+
secp256k1_ge_set_xy(&point, &x, &y);
93+
94+
/* Serialize as compressed pubkey */
95+
ser_ret = secp256k1_eckey_pubkey_serialize(&point, output, &ser_size, 1);
96+
VERIFY_CHECK(ser_ret && ser_size == 33);
97+
(void)ser_ret;
98+
99+
return 1;
100+
}
101+
102+
int secp256k1_silentpayments_create_shared_secret(const secp256k1_context *ctx, unsigned char *shared_secret33, const unsigned char *secret_component, const secp256k1_pubkey *public_component, unsigned char *input_hash) {
103+
unsigned char tweaked_secret_component[32];
104+
/* Sanity check inputs */
105+
ARG_CHECK(shared_secret33 != NULL);
106+
memset(shared_secret33, 0, 33);
107+
ARG_CHECK(public_component != NULL);
108+
ARG_CHECK(secret_component != NULL);
109+
110+
/* Tweak secret component with input hash, if available */
111+
memcpy(tweaked_secret_component, secret_component, 32);
112+
if (input_hash != NULL) {
113+
if (!secp256k1_ec_seckey_tweak_mul(ctx, tweaked_secret_component, input_hash)) {
114+
return 0;
115+
}
116+
}
117+
118+
/* Compute shared_secret = tweaked_secret_component * Public_component */
119+
if (!secp256k1_ecdh(ctx, shared_secret33, public_component, tweaked_secret_component, secp256k1_silentpayments_ecdh_return_pubkey, NULL)) {
120+
return 0;
121+
}
122+
123+
return 1;
124+
}
125+
44126
#endif

0 commit comments

Comments
 (0)