37#include <openssl/rand.h>
38#include <openssl/sha.h>
44static int pubkey_equal(
const secp256k1_context* ctx,
const secp256k1_pubkey* pk1,
const secp256k1_pubkey* pk2) {
45 return secp256k1_ec_pubkey_cmp(ctx, pk1, pk2) == 0;
49 unsigned char amount_scalar[32] = {0};
51 for (
int i = 0; i < 8; ++i) {
52 amount_scalar[31 - i] = (amount >> (i * 8)) & 0xFF;
54 ret = secp256k1_ec_pubkey_create(ctx, mG, amount_scalar);
55 OPENSSL_cleanse(amount_scalar, 32);
62 const secp256k1_context* ctx,
63 unsigned char* privkey,
64 secp256k1_pubkey* pubkey)
67 if (RAND_bytes(privkey, 32) != 1)
return 0;
68 }
while (!secp256k1_ec_seckey_verify(ctx, privkey));
70 if (!secp256k1_ec_pubkey_create(ctx, pubkey, privkey)) {
71 OPENSSL_cleanse(privkey, 32);
80 const secp256k1_context* ctx,
83 const secp256k1_pubkey* pubkey_Q,
85 const unsigned char* blinding_factor
87 secp256k1_pubkey S, mG;
88 const secp256k1_pubkey* pts[2];
91 if (!secp256k1_ec_pubkey_create(ctx, c1, blinding_factor))
return 0;
95 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &S, blinding_factor))
return 0;
102 pts[0] = &mG; pts[1] = &S;
103 if (!secp256k1_ec_pubkey_combine(ctx, c2, pts, 2))
return 0;
112 const secp256k1_context* ctx,
114 const secp256k1_pubkey* c1,
115 const secp256k1_pubkey* c2,
116 const unsigned char* privkey
118 secp256k1_pubkey S, M_target, current_M, G_point, next_M;
119 const secp256k1_pubkey* pts[2];
121 unsigned char one[32] = {0}; one[31] = 1;
125 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &S, privkey))
return 0;
136 if (!secp256k1_ec_pubkey_negate(ctx, &S))
return 0;
137 pts[0] = c2; pts[1] = &S;
138 if (!secp256k1_ec_pubkey_combine(ctx, &M_target, pts, 2))
return 0;
143 if (!secp256k1_ec_pubkey_create(ctx, &G_point, one))
return 0;
146 for (i = 1; i <= 1000000; ++i) {
154 pts[0] = ¤t_M; pts[1] = &G_point;
155 if (!secp256k1_ec_pubkey_combine(ctx, &next_M, pts, 2))
return 0;
165 const secp256k1_context* ctx,
166 secp256k1_pubkey* sum_c1,
167 secp256k1_pubkey* sum_c2,
168 const secp256k1_pubkey* a_c1,
169 const secp256k1_pubkey* a_c2,
170 const secp256k1_pubkey* b_c1,
171 const secp256k1_pubkey* b_c2
173 const secp256k1_pubkey* pts[2];
175 pts[0] = a_c1; pts[1] = b_c1;
176 if (!secp256k1_ec_pubkey_combine(ctx, sum_c1, pts, 2))
return 0;
178 pts[0] = a_c2; pts[1] = b_c2;
179 if (!secp256k1_ec_pubkey_combine(ctx, sum_c2, pts, 2))
return 0;
185 const secp256k1_context* ctx,
186 secp256k1_pubkey* diff_c1,
187 secp256k1_pubkey* diff_c2,
188 const secp256k1_pubkey* a_c1,
189 const secp256k1_pubkey* a_c2,
190 const secp256k1_pubkey* b_c1,
191 const secp256k1_pubkey* b_c2
193 secp256k1_pubkey neg_b_c1 = *b_c1;
194 secp256k1_pubkey neg_b_c2 = *b_c2;
195 const secp256k1_pubkey* pts[2];
197 if (!secp256k1_ec_pubkey_negate(ctx, &neg_b_c1))
return 0;
198 if (!secp256k1_ec_pubkey_negate(ctx, &neg_b_c2))
return 0;
200 pts[0] = a_c1; pts[1] = &neg_b_c1;
201 if (!secp256k1_ec_pubkey_combine(ctx, diff_c1, pts, 2))
return 0;
203 pts[0] = a_c2; pts[1] = &neg_b_c2;
204 if (!secp256k1_ec_pubkey_combine(ctx, diff_c2, pts, 2))
return 0;
212 const secp256k1_context* ctx,
213 secp256k1_pubkey* enc_zero_c1,
214 secp256k1_pubkey* enc_zero_c2,
215 const secp256k1_pubkey* pubkey,
216 const unsigned char* account_id,
217 const unsigned char* mpt_issuance_id
219 unsigned char deterministic_scalar[32];
220 unsigned char hash_input[51];
221 const char* domain =
"EncZero";
226 memcpy(hash_input, domain, 7);
227 memcpy(hash_input + 7, account_id, 20);
228 memcpy(hash_input + 27, mpt_issuance_id, 24);
232 SHA256(hash_input, 51, deterministic_scalar);
237 if (secp256k1_ec_seckey_verify(ctx, deterministic_scalar))
break;
243 memcpy(hash_input, deterministic_scalar, 32);
256 OPENSSL_cleanse(deterministic_scalar, 32);
263 const secp256k1_context* ctx,
264 const secp256k1_pubkey* c1,
265 const secp256k1_pubkey* c2,
266 const secp256k1_pubkey* pubkey_Q,
268 const unsigned char* blinding_factor)
270 secp256k1_pubkey expected_c1, expected_c2, mG, S;
271 const secp256k1_pubkey* pts[2];
274 if (!secp256k1_ec_pubkey_create(ctx, &expected_c1, blinding_factor))
return 0;
281 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &S, blinding_factor))
return 0;
287 pts[0] = &mG; pts[1] = &S;
288 if (!secp256k1_ec_pubkey_combine(ctx, &expected_c2, pts, 2))
return 0;
int secp256k1_elgamal_verify_encryption(const secp256k1_context *ctx, const secp256k1_pubkey *c1, const secp256k1_pubkey *c2, const secp256k1_pubkey *pubkey_Q, uint64_t amount, const unsigned char *blinding_factor)
int generate_canonical_encrypted_zero(const secp256k1_context *ctx, secp256k1_pubkey *enc_zero_c1, secp256k1_pubkey *enc_zero_c2, const secp256k1_pubkey *pubkey, const unsigned char *account_id, const unsigned char *mpt_issuance_id)
Generates the canonical encrypted zero for a given MPT token instance.
int secp256k1_elgamal_subtract(const secp256k1_context *ctx, secp256k1_pubkey *diff_c1, secp256k1_pubkey *diff_c2, const secp256k1_pubkey *a_c1, const secp256k1_pubkey *a_c2, const secp256k1_pubkey *b_c1, const secp256k1_pubkey *b_c2)
Homomorphically subtracts two ElGamal ciphertexts.
int secp256k1_elgamal_add(const secp256k1_context *ctx, secp256k1_pubkey *sum_c1, secp256k1_pubkey *sum_c2, const secp256k1_pubkey *a_c1, const secp256k1_pubkey *a_c2, const secp256k1_pubkey *b_c1, const secp256k1_pubkey *b_c2)
Homomorphically adds two ElGamal ciphertexts.
int secp256k1_elgamal_decrypt(const secp256k1_context *ctx, uint64_t *amount, const secp256k1_pubkey *c1, const secp256k1_pubkey *c2, const unsigned char *privkey)
Decrypts an ElGamal ciphertext to recover the amount.
int secp256k1_elgamal_encrypt(const secp256k1_context *ctx, secp256k1_pubkey *c1, secp256k1_pubkey *c2, const secp256k1_pubkey *pubkey_Q, uint64_t amount, const unsigned char *blinding_factor)
Encrypts a 64-bit amount using ElGamal.
int secp256k1_elgamal_generate_keypair(const secp256k1_context *ctx, unsigned char *privkey, secp256k1_pubkey *pubkey)
Generates a new secp256k1 key pair.
static int compute_amount_point(const secp256k1_context *ctx, secp256k1_pubkey *mG, uint64_t amount)
static int pubkey_equal(const secp256k1_context *ctx, const secp256k1_pubkey *pk1, const secp256k1_pubkey *pk2)