mpt-crypto
Confidential Multi-Purpose Tokens Cryptographic Library
Loading...
Searching...
No Matches
commitments.c
Go to the documentation of this file.
1
28#include "secp256k1_mpt.h"
29#include <string.h>
30#include <openssl/sha.h>
31#include <openssl/crypto.h> // For OPENSSL_cleanse
32
33/* --- Internal Helpers --- */
34
49 const secp256k1_context* ctx,
50 secp256k1_pubkey* out,
51 const unsigned char* label,
52 size_t label_len,
53 uint32_t index
54) {
55 unsigned char hash[32];
56 unsigned char compressed[33];
57 uint32_t ctr = 0;
58
59 unsigned char idx_be[4] = {
60 (unsigned char)(index >> 24), (unsigned char)(index >> 16),
61 (unsigned char)(index >> 8), (unsigned char)(index & 0xFF)
62 };
63
64 /* Try-and-increment loop */
65 while (ctr < 0xFFFFFFFFu) {
66 unsigned char ctr_be[4] = {
67 (unsigned char)(ctr >> 24), (unsigned char)(ctr >> 16),
68 (unsigned char)(ctr >> 8), (unsigned char)(ctr & 0xFF)
69 };
70
71 SHA256_CTX sha;
72 SHA256_Init(&sha);
73 SHA256_Update(&sha, "MPT_BULLETPROOF_V1_NUMS", 23); // Domain Sep
74 SHA256_Update(&sha, "secp256k1", 9); // Curve Label
75
76 if (label && label_len > 0) {
77 SHA256_Update(&sha, label, label_len);
78 }
79
80 SHA256_Update(&sha, idx_be, 4);
81 SHA256_Update(&sha, ctr_be, 4);
82 SHA256_Final(hash, &sha);
83
84 /* Construct compressed point candidate */
85 compressed[0] = 0x02; /* Force even Y (standard convention for unique points) */
86 memcpy(&compressed[1], hash, 32);
87
88 /* Check validity on curve */
89 if (secp256k1_ec_pubkey_parse(ctx, out, compressed, 33) == 1) {
90 return 1;
91 }
92 ctr++;
93 }
94 return 0; // Extremely unlikely to reach here
95}
96
108int secp256k1_mpt_get_h_generator(const secp256k1_context* ctx, secp256k1_pubkey* h) {
109 return secp256k1_mpt_hash_to_point_nums(ctx, h, (const unsigned char*)"H", 1, 0);
110}
111
125 const secp256k1_context* ctx,
126 secp256k1_pubkey* vec,
127 size_t n,
128 const unsigned char* label,
129 size_t label_len
130) {
131 for (uint32_t i = 0; i < (uint32_t)n; i++) {
132 if (!secp256k1_mpt_hash_to_point_nums(ctx, &vec[i], label, label_len, i)) {
133 return 0;
134 }
135 }
136 return 1;
137}
138
139/* --- Public API --- */
140
150 const secp256k1_context* ctx,
151 secp256k1_pubkey* commitment,
152 uint64_t amount,
153 const unsigned char* rho
154) {
155 secp256k1_pubkey mG, rH, H;
156 unsigned char m_scalar[32] = {0};
157 int ok = 0;
158
159 /* 0. Input Check */
160 if (!secp256k1_ec_seckey_verify(ctx, rho)) return 0;
161
162 /* 1. Calculate rho*H (Blinding Term) */
163 /* We do this first so we can use it directly if amount is 0 */
164 if (!secp256k1_mpt_get_h_generator(ctx, &H)) return 0;
165
166 rH = H;
167 if (!secp256k1_ec_pubkey_tweak_mul(ctx, &rH, rho)) return 0;
168
169 /* 2. Handle Zero Amount Case */
170 if (amount == 0) {
171 /* If m=0, C = 0*G + r*H = r*H */
172 *commitment = rH;
173 return 1;
174 }
175
176 /* 3. Calculate m*G (Value Term) */
177 /* Convert uint64 amount to big-endian scalar */
178 for (int i = 0; i < 8; i++) {
179 m_scalar[31 - i] = (amount >> (i * 8)) & 0xFF;
180 }
181
182 /* This check passes now because we handled amount==0 above */
183 if (!secp256k1_ec_pubkey_create(ctx, &mG, m_scalar)) goto cleanup;
184
185 /* 4. Combine: C = mG + rH */
186 const secp256k1_pubkey* points[2] = {&mG, &rH};
187 if (!secp256k1_ec_pubkey_combine(ctx, commitment, points, 2)) goto cleanup;
188
189 ok = 1;
190
191 cleanup:
192 /* Securely clear the amount scalar from stack */
193 OPENSSL_cleanse(m_scalar, 32);
194 return ok;
195}
int secp256k1_mpt_pedersen_commit(const secp256k1_context *ctx, secp256k1_pubkey *commitment, uint64_t amount, const unsigned char *rho)
Creates a Pedersen Commitment C = amount*G + rho*H.
int secp256k1_mpt_get_generator_vector(const secp256k1_context *ctx, secp256k1_pubkey *vec, size_t n, const unsigned char *label, size_t label_len)
Generates a vector of N independent NUMS generators.
int secp256k1_mpt_get_h_generator(const secp256k1_context *ctx, secp256k1_pubkey *h)
Derives the secondary base point (H) for Pedersen commitments.
int secp256k1_mpt_hash_to_point_nums(const secp256k1_context *ctx, secp256k1_pubkey *out, const unsigned char *label, size_t label_len, uint32_t index)
Deterministically derives a NUMS (Nothing-Up-My-Sleeve) generator point.
Definition commitments.c:48