GNUnet 0.21.1
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 nonce, sizeof (*nonce),
91 NULL, 0));
92 map_to_scalar_subgroup (&r[0].scalar);
93 map_to_scalar_subgroup (&r[1].scalar);
94}
95
96
97void
99 struct GNUNET_CRYPTO_CsRPublic *r_pub)
100{
101 GNUNET_assert (0 ==
102 crypto_scalarmult_ed25519_base_noclamp (r_pub->point.y,
103 r_priv->scalar.d));
104}
105
106
107void
109 const struct GNUNET_CRYPTO_CsBlindingNonce *blind_seed,
111{
113 GNUNET_YES ==
115 sizeof (struct GNUNET_CRYPTO_CsBlindingSecret) * 2,
116 GCRY_MD_SHA512,
117 GCRY_MD_SHA256,
118 "alphabeta",
119 strlen ("alphabeta"),
120 blind_seed,
121 sizeof(*blind_seed),
122 NULL,
123 0));
128}
129
130
131/*
132order of subgroup required for scalars by libsodium
1332^252 + 27742317777372353535851937790883648493
134copied from https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
135and converted to big endian
136*/
137static const unsigned char L_BIG_ENDIAN[32] = {
138 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7,
140 0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed
141};
142
143
151static void
153 const void *msg,
154 size_t msg_len,
155 const struct GNUNET_CRYPTO_CsPublicKey *pub,
156 struct GNUNET_CRYPTO_CsC *c)
157{
158 // SHA-512 hash of R' and message
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 struct GNUNET_HashCode prehash;
168
169 GNUNET_CRYPTO_hash (r_m_concat,
170 r_m_concat_len,
171 &prehash);
172
173 // modulus converted to MPI representation
174 gcry_mpi_t l_mpi;
177 sizeof(L_BIG_ENDIAN));
178
179 // calculate full domain hash
180 gcry_mpi_t c_mpi;
182 l_mpi,
183 pub,
184 sizeof(struct GNUNET_CRYPTO_CsPublicKey),
185 &prehash,
186 sizeof(struct GNUNET_HashCode),
187 "Curve25519FDH");
188 gcry_mpi_release (l_mpi);
189
190 // convert c from mpi
191 unsigned char c_big_endian[256 / 8];
193 sizeof(c_big_endian),
194 c_mpi);
195 gcry_mpi_release (c_mpi);
196 for (size_t i = 0; i<32; i++)
197 c->scalar.d[i] = c_big_endian[31 - i];
198}
199
200
209static void
211 const struct GNUNET_CRYPTO_CsRPublic *r_pub,
212 const struct GNUNET_CRYPTO_CsPublicKey *pub,
213 struct GNUNET_CRYPTO_CsRPublic *blinded_r_pub)
214{
215 // R'i = Ri + alpha i*G + beta i*pub
216 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base;
217 GNUNET_assert (0 ==
218 crypto_scalarmult_ed25519_base_noclamp (
219 alpha_mul_base.y,
220 bs->alpha.d));
221 struct GNUNET_CRYPTO_Cs25519Point beta_mul_pub;
222 GNUNET_assert (0 ==
223 crypto_scalarmult_ed25519_noclamp (
224 beta_mul_pub.y,
225 bs->beta.d,
226 pub->point.y));
227 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base_plus_beta_mul_pub;
228 GNUNET_assert (0 == crypto_core_ed25519_add (
229 alpha_mul_base_plus_beta_mul_pub.y,
230 alpha_mul_base.y,
231 beta_mul_pub.y));
232 GNUNET_assert (0 ==
233 crypto_core_ed25519_add (
234 blinded_r_pub->point.y,
235 r_pub->point.y,
236 alpha_mul_base_plus_beta_mul_pub.y));
237}
238
239
240void
242 const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
243 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
244 const struct GNUNET_CRYPTO_CsPublicKey *pub,
245 const void *msg,
246 size_t msg_len,
247 struct GNUNET_CRYPTO_CsC blinded_c[2],
248 struct GNUNET_CRYPTO_CSPublicRPairP *r_pub_blind)
249{
250 /* for i 0/1: R'i = Ri + alpha i*G + beta i*pub */
251 calc_r_dash (&bs[0],
252 &r_pub[0],
253 pub,
254 &r_pub_blind->r_pub[0]);
255 calc_r_dash (&bs[1],
256 &r_pub[1],
257 pub,
258 &r_pub_blind->r_pub[1]);
259
260 /* for i 0/1: c'i = H(R'i, msg) */
261 struct GNUNET_CRYPTO_CsC c_dash_0;
262 struct GNUNET_CRYPTO_CsC c_dash_1;
263 cs_full_domain_hash (&r_pub_blind->r_pub[0],
264 msg,
265 msg_len,
266 pub,
267 &c_dash_0);
268 cs_full_domain_hash (&r_pub_blind->r_pub[1],
269 msg,
270 msg_len,
271 pub,
272 &c_dash_1);
273
274 /* for i 0/1: ci = c'i + beta i mod p */
275 crypto_core_ed25519_scalar_add (blinded_c[0].scalar.d,
276 c_dash_0.scalar.d,
277 bs[0].beta.d);
278 crypto_core_ed25519_scalar_add (blinded_c[1].scalar.d,
279 c_dash_1.scalar.d,
280 bs[1].beta.d);
281}
282
283
284void
286 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
287 const struct GNUNET_CRYPTO_CsRSecret r[2],
288 const struct GNUNET_CRYPTO_CsBlindedMessage *bm,
289 struct GNUNET_CRYPTO_CsBlindSignature *cs_blind_sig)
290{
291 struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
292 uint32_t hkdf_out;
293
294 /* derive clause session identifier b (random bit) */
296 GNUNET_CRYPTO_hkdf (&hkdf_out,
297 sizeof (hkdf_out),
298 GCRY_MD_SHA512,
299 GCRY_MD_SHA256,
300 "b",
301 strlen ("b"),
302 priv,
303 sizeof (*priv),
304 &bm->nonce,
305 sizeof (bm->nonce),
306 NULL,
307 0));
308 cs_blind_sig->b = hkdf_out % 2;
309
310 /* s = r_b + c_b * priv */
311 crypto_core_ed25519_scalar_mul (c_b_mul_priv.d,
312 bm->c[cs_blind_sig->b].scalar.d,
313 priv->scalar.d);
314 crypto_core_ed25519_scalar_add (cs_blind_sig->s_scalar.scalar.d,
315 r[cs_blind_sig->b].scalar.d,
316 c_b_mul_priv.d);
317}
318
319
320void
322 const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
323 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
324 struct GNUNET_CRYPTO_CsS *signature_scalar)
325{
326 crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
327 blinded_signature_scalar->scalar.d,
328 bs->alpha.d);
329}
330
331
334 const struct GNUNET_CRYPTO_CsPublicKey *pub,
335 const void *msg,
336 size_t msg_len)
337{
338 // calculate c' = H(R, m)
339 struct GNUNET_CRYPTO_CsC c_dash;
340
342 msg,
343 msg_len,
344 pub,
345 &c_dash);
346
347 // s'G ?= R' + c' pub
348 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
349 GNUNET_assert (0 ==
350 crypto_scalarmult_ed25519_base_noclamp (
351 sig_scal_mul_base.y,
352 sig->s_scalar.scalar.d));
353 struct GNUNET_CRYPTO_Cs25519Point c_dash_mul_pub;
354 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_dash_mul_pub.y,
355 c_dash.scalar.d,
356 pub->point.y));
357 struct GNUNET_CRYPTO_Cs25519Point R_add_c_dash_mul_pub;
358 GNUNET_assert (0 == crypto_core_ed25519_add (R_add_c_dash_mul_pub.y,
359 sig->r_point.point.y,
360 c_dash_mul_pub.y));
361
362 return 0 == GNUNET_memcmp (&sig_scal_mul_base,
363 &R_add_c_dash_mul_pub)
364 ? GNUNET_OK
366}
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static const unsigned char L_BIG_ENDIAN[32]
Definition: crypto_cs.c:137
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:210
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:152
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:47
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
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hkdf(void *result, size_t out_len, int xtr_algo, int prf_algo, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_hkdf.c:341
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:70
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:98
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:95
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:321
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:241
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
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:333
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:285
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:108
@ 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.