GNUnet 0.26.2-20-ga2d76f2e4
 
Loading...
Searching...
No Matches
crypto_cs.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014,2016,2019, 2023 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include <sodium.h>
31#include <gcrypt.h>
32
44void
46{
47 crypto_core_ed25519_scalar_random (priv->scalar.d);
48}
49
50
51void
53 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
55{
56 GNUNET_assert (0 ==
57 crypto_scalarmult_ed25519_base_noclamp (pub->point.y,
58 priv->scalar.d));
59}
60
61
68static void
70{
71 /* perform clamping as described in RFC7748 */
72 scalar->d[0] &= 248;
73 scalar->d[31] &= 127;
74 scalar->d[31] |= 64;
75}
76
77
78void
80 const char *seed,
81 const struct GNUNET_CRYPTO_CsPrivateKey *lts,
82 struct GNUNET_CRYPTO_CsRSecret r[2])
83{
85 GNUNET_YES ==
87 r, sizeof (struct GNUNET_CRYPTO_CsRSecret) * 2,
88 seed, strlen (seed),
89 lts, sizeof (*lts),
90 GNUNET_CRYPTO_kdf_arg (nonce, sizeof (*nonce))));
91 map_to_scalar_subgroup (&r[0].scalar);
92 map_to_scalar_subgroup (&r[1].scalar);
93}
94
95
96void
98 struct GNUNET_CRYPTO_CsRPublic *r_pub)
99{
100 GNUNET_assert (0 ==
101 crypto_scalarmult_ed25519_base_noclamp (r_pub->point.y,
102 r_priv->scalar.d));
103}
104
105
106void
108 const struct GNUNET_CRYPTO_CsBlindingNonce *blind_seed,
110{
112 GNUNET_YES ==
114 bs,
115 sizeof (struct GNUNET_CRYPTO_CsBlindingSecret) * 2,
116 "alphabeta",
117 strlen ("alphabeta"),
118 blind_seed,
119 sizeof(*blind_seed)));
124}
125
126
127/*
128order of subgroup required for scalars by libsodium
1292^252 + 27742317777372353535851937790883648493
130copied from https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
131and converted to big endian
132*/
133static const unsigned char L_BIG_ENDIAN[32] = {
134 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7,
136 0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed
137};
138
139
147static void
149 const void *msg,
150 size_t msg_len,
151 const struct GNUNET_CRYPTO_CsPublicKey *pub,
152 struct GNUNET_CRYPTO_CsC *c)
153{
154 // SHA-512 hash of R' and message
155 struct GNUNET_HashCode prehash;
156 gcry_mpi_t l_mpi;
157 gcry_mpi_t c_mpi;
158 unsigned char c_big_endian[256 / 8];
159 size_t r_m_concat_len = sizeof(struct GNUNET_CRYPTO_CsRPublic) + msg_len;
160 char r_m_concat[r_m_concat_len];
161 memcpy (r_m_concat,
162 r_dash,
163 sizeof(struct GNUNET_CRYPTO_CsRPublic));
164 memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic),
165 msg,
166 msg_len);
167
168 GNUNET_CRYPTO_hash (r_m_concat,
169 r_m_concat_len,
170 &prehash);
171
172 // modulus converted to MPI representation
175 sizeof(L_BIG_ENDIAN));
176
177 // calculate full domain hash
179 l_mpi,
180 pub,
181 sizeof(struct GNUNET_CRYPTO_CsPublicKey),
182 &prehash,
183 sizeof(struct GNUNET_HashCode),
184 "Curve25519FDH");
185 gcry_mpi_release (l_mpi);
186
187 // convert c from mpi
189 sizeof(c_big_endian),
190 c_mpi);
191 gcry_mpi_release (c_mpi);
192 for (size_t i = 0; i<32; i++)
193 c->scalar.d[i] = c_big_endian[31 - i];
194}
195
196
205static void
207 const struct GNUNET_CRYPTO_CsRPublic *r_pub,
208 const struct GNUNET_CRYPTO_CsPublicKey *pub,
209 struct GNUNET_CRYPTO_CsRPublic *blinded_r_pub)
210{
211 // R'i = Ri + alpha i*G + beta i*pub
212 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base;
213 struct GNUNET_CRYPTO_Cs25519Point beta_mul_pub;
214 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base_plus_beta_mul_pub;
215 GNUNET_assert (0 ==
216 crypto_scalarmult_ed25519_base_noclamp (
217 alpha_mul_base.y,
218 bs->alpha.d));
219 GNUNET_assert (0 ==
220 crypto_scalarmult_ed25519_noclamp (
221 beta_mul_pub.y,
222 bs->beta.d,
223 pub->point.y));
224 GNUNET_assert (0 == crypto_core_ed25519_add (
225 alpha_mul_base_plus_beta_mul_pub.y,
226 alpha_mul_base.y,
227 beta_mul_pub.y));
228 GNUNET_assert (0 ==
229 crypto_core_ed25519_add (
230 blinded_r_pub->point.y,
231 r_pub->point.y,
232 alpha_mul_base_plus_beta_mul_pub.y));
233}
234
235
236void
238 const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
239 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
240 const struct GNUNET_CRYPTO_CsPublicKey *pub,
241 const void *msg,
242 size_t msg_len,
243 struct GNUNET_CRYPTO_CsC blinded_c[2],
244 struct GNUNET_CRYPTO_CSPublicRPairP *r_pub_blind)
245{
246 struct GNUNET_CRYPTO_CsC c_dash_0;
247 struct GNUNET_CRYPTO_CsC c_dash_1;
248 /* for i 0/1: R'i = Ri + alpha i*G + beta i*pub */
249 calc_r_dash (&bs[0],
250 &r_pub[0],
251 pub,
252 &r_pub_blind->r_pub[0]);
253 calc_r_dash (&bs[1],
254 &r_pub[1],
255 pub,
256 &r_pub_blind->r_pub[1]);
257
258 /* for i 0/1: c'i = H(R'i, msg) */
259 cs_full_domain_hash (&r_pub_blind->r_pub[0],
260 msg,
261 msg_len,
262 pub,
263 &c_dash_0);
264 cs_full_domain_hash (&r_pub_blind->r_pub[1],
265 msg,
266 msg_len,
267 pub,
268 &c_dash_1);
269
270 /* for i 0/1: ci = c'i + beta i mod p */
271 crypto_core_ed25519_scalar_add (blinded_c[0].scalar.d,
272 c_dash_0.scalar.d,
273 bs[0].beta.d);
274 crypto_core_ed25519_scalar_add (blinded_c[1].scalar.d,
275 c_dash_1.scalar.d,
276 bs[1].beta.d);
277}
278
279
280void
282 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
283 const struct GNUNET_CRYPTO_CsRSecret r[2],
284 const struct GNUNET_CRYPTO_CsBlindedMessage *bm,
285 struct GNUNET_CRYPTO_CsBlindSignature *cs_blind_sig)
286{
287 struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
288 uint32_t hkdf_out;
289
290 /* derive clause session identifier b (random bit) */
293 &hkdf_out,
294 sizeof (hkdf_out),
295 "b",
296 strlen ("b"),
297 priv,
298 sizeof (*priv),
300 cs_blind_sig->b = hkdf_out % 2;
301
302 /* s = r_b + c_b * priv */
303 crypto_core_ed25519_scalar_mul (c_b_mul_priv.d,
304 bm->c[cs_blind_sig->b].scalar.d,
305 priv->scalar.d);
306 crypto_core_ed25519_scalar_add (cs_blind_sig->s_scalar.scalar.d,
307 r[cs_blind_sig->b].scalar.d,
308 c_b_mul_priv.d);
309}
310
311
312void
314 const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
315 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
316 struct GNUNET_CRYPTO_CsS *signature_scalar)
317{
318 crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
319 blinded_signature_scalar->scalar.d,
320 bs->alpha.d);
321}
322
323
326 const struct GNUNET_CRYPTO_CsPublicKey *pub,
327 const void *msg,
328 size_t msg_len)
329{
330 // calculate c' = H(R, m)
331 struct GNUNET_CRYPTO_CsC c_dash;
332 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
333 struct GNUNET_CRYPTO_Cs25519Point c_dash_mul_pub;
334 struct GNUNET_CRYPTO_Cs25519Point R_add_c_dash_mul_pub;
335
337 msg,
338 msg_len,
339 pub,
340 &c_dash);
341
342 // s'G ?= R' + c' pub
343 GNUNET_assert (0 ==
344 crypto_scalarmult_ed25519_base_noclamp (
345 sig_scal_mul_base.y,
346 sig->s_scalar.scalar.d));
347 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_dash_mul_pub.y,
348 c_dash.scalar.d,
349 pub->point.y));
350 GNUNET_assert (0 == crypto_core_ed25519_add (R_add_c_dash_mul_pub.y,
351 sig->r_point.point.y,
352 c_dash_mul_pub.y));
353
354 return 0 == GNUNET_memcmp (&sig_scal_mul_base,
355 &R_add_c_dash_mul_pub)
356 ? GNUNET_OK
358}
struct GNUNET_MessageHeader * msg
Definition 005.c:2
static const unsigned char L_BIG_ENDIAN[32]
Definition crypto_cs.c:133
static void map_to_scalar_subgroup(struct GNUNET_CRYPTO_Cs25519Scalar *scalar)
Maps 32 random bytes to a scalar.
Definition crypto_cs.c:69
static void calc_r_dash(const struct GNUNET_CRYPTO_CsBlindingSecret *bs, const struct GNUNET_CRYPTO_CsRPublic *r_pub, const struct GNUNET_CRYPTO_CsPublicKey *pub, struct GNUNET_CRYPTO_CsRPublic *blinded_r_pub)
calculate R'
Definition crypto_cs.c:206
static void cs_full_domain_hash(const struct GNUNET_CRYPTO_CsRPublic *r_dash, const void *msg, size_t msg_len, const struct GNUNET_CRYPTO_CsPublicKey *pub, struct GNUNET_CRYPTO_CsC *c)
Computes a Hash of (R', m) mapped to a Curve25519 scalar.
Definition crypto_cs.c:148
static uint8_t seed
static struct GNUNET_CRYPTO_EddsaPublicKey pub
static float beta
Percentage of total peer number in the view to send random PULLs to.
static float alpha
Percentage of total peer number in the view to send random PUSHes to.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
#define GNUNET_CRYPTO_hkdf_gnunet(result, out_len, xts, xts_len, skm, skm_len,...)
A peculiar HKDF instantiation that tried to mimic Truncated NMAC.
void GNUNET_CRYPTO_mpi_scan_unsigned(gcry_mpi_t *result, const void *data, size_t size)
Convert data buffer into MPI value.
Definition crypto_mpi.c:132
void GNUNET_CRYPTO_cs_r_get_public(const struct GNUNET_CRYPTO_CsRSecret *r_priv, struct GNUNET_CRYPTO_CsRPublic *r_pub)
Extract the public R of the given secret r.
Definition crypto_cs.c:97
void GNUNET_CRYPTO_kdf_mod_mpi(gcry_mpi_t *r, gcry_mpi_t n, const void *xts, size_t xts_len, const void *skm, size_t skm_len, const char *ctx)
Deterministically generate a pseudo-random number uniformly from the integers modulo a libgcrypt mpi.
Definition crypto_kdf.c:38
void GNUNET_CRYPTO_cs_r_derive(const struct GNUNET_CRYPTO_CsSessionNonce *nonce, const char *seed, const struct GNUNET_CRYPTO_CsPrivateKey *lts, struct GNUNET_CRYPTO_CsRSecret r[2])
Derive a new secret r pair r0 and r1.
Definition crypto_cs.c:79
void GNUNET_CRYPTO_cs_private_key_get_public(const struct GNUNET_CRYPTO_CsPrivateKey *priv, struct GNUNET_CRYPTO_CsPublicKey *pub)
Extract the public key of the given private key.
Definition crypto_cs.c:52
void GNUNET_CRYPTO_cs_unblind(const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar, const struct GNUNET_CRYPTO_CsBlindingSecret *bs, struct GNUNET_CRYPTO_CsS *signature_scalar)
Unblind a blind-signed signature using a c that was blinded.
Definition crypto_cs.c:313
void GNUNET_CRYPTO_mpi_print_unsigned(void *buf, size_t size, gcry_mpi_t val)
Output the given MPI value to the given buffer in network byte order.
Definition crypto_mpi.c:79
void GNUNET_CRYPTO_cs_calc_blinded_c(const struct GNUNET_CRYPTO_CsBlindingSecret bs[2], const struct GNUNET_CRYPTO_CsRPublic r_pub[2], const struct GNUNET_CRYPTO_CsPublicKey *pub, const void *msg, size_t msg_len, struct GNUNET_CRYPTO_CsC blinded_c[2], struct GNUNET_CRYPTO_CSPublicRPairP *r_pub_blind)
Calculate two blinded c's.
Definition crypto_cs.c:237
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_CRYPTO_kdf_arg_auto(d)
#define GNUNET_CRYPTO_kdf_arg(d, s)
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_cs_verify(const struct GNUNET_CRYPTO_CsSignature *sig, const struct GNUNET_CRYPTO_CsPublicKey *pub, const void *msg, size_t msg_len)
Verify whether the given message corresponds to the given signature and the signature is valid with r...
Definition crypto_cs.c:325
GNUNET_GenericReturnValue
Named constants for return values.
void GNUNET_CRYPTO_cs_sign_derive(const struct GNUNET_CRYPTO_CsPrivateKey *priv, const struct GNUNET_CRYPTO_CsRSecret r[2], const struct GNUNET_CRYPTO_CsBlindedMessage *bm, struct GNUNET_CRYPTO_CsBlindSignature *cs_blind_sig)
Sign a blinded c.
Definition crypto_cs.c:281
void GNUNET_CRYPTO_cs_private_key_generate(struct GNUNET_CRYPTO_CsPrivateKey *priv)
IMPLEMENTATION NOTICE:
Definition crypto_cs.c:45
void GNUNET_CRYPTO_cs_blinding_secrets_derive(const struct GNUNET_CRYPTO_CsBlindingNonce *blind_seed, struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
Derives new random blinding factors.
Definition crypto_cs.c:107
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Pair of Public R values for Cs denominations.
struct GNUNET_CRYPTO_CsRPublic r_pub[2]
unsigned char y[crypto_core_ed25519_BYTES]
This is a point on the Curve25519.
unsigned char d[crypto_core_ed25519_SCALARBYTES]
32 byte scalar
blinded s in the signature
struct GNUNET_CRYPTO_Cs25519Scalar scalar
The Sign Answer for Clause Blind Schnorr signature.
struct GNUNET_CRYPTO_CsBlindS s_scalar
The blinded s scalar calculated from c_b.
unsigned int b
To make ROS problem harder, the signer chooses an unpredictable b and only calculates signature of c_...
CS Parameters derived from the message during blinding to create blinded signature.
struct GNUNET_CRYPTO_CsC c[2]
The Clause Schnorr c_0 and c_1 containing the blinded message.
struct GNUNET_CRYPTO_CsSessionNonce nonce
Nonce used in initial request.
Nonce for computing blinding factors.
Secret used for blinding (alpha and beta).
struct GNUNET_CRYPTO_Cs25519Scalar alpha
struct GNUNET_CRYPTO_Cs25519Scalar beta
Schnorr c to be signed.
struct GNUNET_CRYPTO_Cs25519Scalar scalar
The private information of an Schnorr key pair.
struct GNUNET_CRYPTO_Cs25519Scalar scalar
The public information of an Schnorr key pair.
the public R (derived from r) used in c
struct GNUNET_CRYPTO_Cs25519Point point
the private r used in the signature
struct GNUNET_CRYPTO_Cs25519Scalar scalar
s in the signature
struct GNUNET_CRYPTO_Cs25519Scalar scalar
Nonce for the session, picked by client, shared with the signer.
CS Signtature containing scalar s and point R.
struct GNUNET_CRYPTO_CsS s_scalar
Schnorr signatures are composed of a scalar s and a curve point.
struct GNUNET_CRYPTO_CsRPublic r_point
Curve point of the Schnorr signature.
A 512-bit hashcode.