|
7 | 7 | #define SECP256K1_MODULE_SILENTPAYMENTS_MAIN_H
|
8 | 8 |
|
9 | 9 | #include "../../../include/secp256k1.h"
|
| 10 | +#include "../../../include/secp256k1_ecdh.h" |
| 11 | +#include "../../../include/secp256k1_extrakeys.h" |
10 | 12 | #include "../../../include/secp256k1_silentpayments.h"
|
11 | 13 |
|
12 | 14 | /** 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
|
41 | 43 | return 1;
|
42 | 44 | }
|
43 | 45 |
|
| 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 | + |
44 | 126 | #endif
|
0 commit comments