GNUnet 0.22.2
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)
116 * 2,
117 "alphabeta",
118 strlen ("alphabeta"),
119 blind_seed,
120 sizeof(*blind_seed),
121 NULL,
122 0));
127}
128
129
130/*
131order of subgroup required for scalars by libsodium
1322^252 + 27742317777372353535851937790883648493
133copied from https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
134and converted to big endian
135*/
136static const unsigned char L_BIG_ENDIAN[32] = {
137 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7,
139 0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed
140};
141
142
150static void
152 const void *msg,
153 size_t msg_len,
154 const struct GNUNET_CRYPTO_CsPublicKey *pub,
155 struct GNUNET_CRYPTO_CsC *c)
156{
157 // SHA-512 hash of R' and message
158 struct GNUNET_HashCode prehash;
159 gcry_mpi_t l_mpi;
160 gcry_mpi_t c_mpi;
161 unsigned char c_big_endian[256 / 8];
162 size_t r_m_concat_len = sizeof(struct GNUNET_CRYPTO_CsRPublic) + msg_len;
163 char r_m_concat[r_m_concat_len];
164 memcpy (r_m_concat,
165 r_dash,
166 sizeof(struct GNUNET_CRYPTO_CsRPublic));
167 memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic),
168 msg,
169 msg_len);
170
171 GNUNET_CRYPTO_hash (r_m_concat,
172 r_m_concat_len,
173 &prehash);
174
175 // modulus converted to MPI representation
178 sizeof(L_BIG_ENDIAN));
179
180 // calculate full domain hash
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
192 sizeof(c_big_endian),
193 c_mpi);
194 gcry_mpi_release (c_mpi);
195 for (size_t i = 0; i<32; i++)
196 c->scalar.d[i] = c_big_endian[31 - i];
197}
198
199
208static void
210 const struct GNUNET_CRYPTO_CsRPublic *r_pub,
211 const struct GNUNET_CRYPTO_CsPublicKey *pub,
212 struct GNUNET_CRYPTO_CsRPublic *blinded_r_pub)
213{
214 // R'i = Ri + alpha i*G + beta i*pub
215 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base;
216 struct GNUNET_CRYPTO_Cs25519Point beta_mul_pub;
217 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base_plus_beta_mul_pub;
218 GNUNET_assert (0 ==
219 crypto_scalarmult_ed25519_base_noclamp (
220 alpha_mul_base.y,
221 bs->alpha.d));
222 GNUNET_assert (0 ==
223 crypto_scalarmult_ed25519_noclamp (
224 beta_mul_pub.y,
225 bs->beta.d,
226 pub->point.y));
227 GNUNET_assert (0 == crypto_core_ed25519_add (
228 alpha_mul_base_plus_beta_mul_pub.y,
229 alpha_mul_base.y,
230 beta_mul_pub.y));
231 GNUNET_assert (0 ==
232 crypto_core_ed25519_add (
233 blinded_r_pub->point.y,
234 r_pub->point.y,
235 alpha_mul_base_plus_beta_mul_pub.y));
236}
237
238
239void
241 const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
242 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
243 const struct GNUNET_CRYPTO_CsPublicKey *pub,
244 const void *msg,
245 size_t msg_len,
246 struct GNUNET_CRYPTO_CsC blinded_c[2],
247 struct GNUNET_CRYPTO_CSPublicRPairP *r_pub_blind)
248{
249 struct GNUNET_CRYPTO_CsC c_dash_0;
250 struct GNUNET_CRYPTO_CsC c_dash_1;
251 /* for i 0/1: R'i = Ri + alpha i*G + beta i*pub */
252 calc_r_dash (&bs[0],
253 &r_pub[0],
254 pub,
255 &r_pub_blind->r_pub[0]);
256 calc_r_dash (&bs[1],
257 &r_pub[1],
258 pub,
259 &r_pub_blind->r_pub[1]);
260
261 /* for i 0/1: c'i = H(R'i, msg) */
262 cs_full_domain_hash (&r_pub_blind->r_pub[0],
263 msg,
264 msg_len,
265 pub,
266 &c_dash_0);
267 cs_full_domain_hash (&r_pub_blind->r_pub[1],
268 msg,
269 msg_len,
270 pub,
271 &c_dash_1);
272
273 /* for i 0/1: ci = c'i + beta i mod p */
274 crypto_core_ed25519_scalar_add (blinded_c[0].scalar.d,
275 c_dash_0.scalar.d,
276 bs[0].beta.d);
277 crypto_core_ed25519_scalar_add (blinded_c[1].scalar.d,
278 c_dash_1.scalar.d,
279 bs[1].beta.d);
280}
281
282
283void
285 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
286 const struct GNUNET_CRYPTO_CsRSecret r[2],
287 const struct GNUNET_CRYPTO_CsBlindedMessage *bm,
288 struct GNUNET_CRYPTO_CsBlindSignature *cs_blind_sig)
289{
290 struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
291 uint32_t hkdf_out;
292
293 /* derive clause session identifier b (random bit) */
295 GNUNET_CRYPTO_hkdf_gnunet (&hkdf_out,
296 sizeof (hkdf_out),
297 "b",
298 strlen ("b"),
299 priv,
300 sizeof (*priv),
301 &bm->nonce,
302 sizeof (bm->nonce),
303 NULL,
304 0));
305 cs_blind_sig->b = hkdf_out % 2;
306
307 /* s = r_b + c_b * priv */
308 crypto_core_ed25519_scalar_mul (c_b_mul_priv.d,
309 bm->c[cs_blind_sig->b].scalar.d,
310 priv->scalar.d);
311 crypto_core_ed25519_scalar_add (cs_blind_sig->s_scalar.scalar.d,
312 r[cs_blind_sig->b].scalar.d,
313 c_b_mul_priv.d);
314}
315
316
317void
319 const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
320 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
321 struct GNUNET_CRYPTO_CsS *signature_scalar)
322{
323 crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
324 blinded_signature_scalar->scalar.d,
325 bs->alpha.d);
326}
327
328
331 const struct GNUNET_CRYPTO_CsPublicKey *pub,
332 const void *msg,
333 size_t msg_len)
334{
335 // calculate c' = H(R, m)
336 struct GNUNET_CRYPTO_CsC c_dash;
337 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
338 struct GNUNET_CRYPTO_Cs25519Point c_dash_mul_pub;
339 struct GNUNET_CRYPTO_Cs25519Point R_add_c_dash_mul_pub;
340
342 msg,
343 msg_len,
344 pub,
345 &c_dash);
346
347 // s'G ?= R' + c' pub
348 GNUNET_assert (0 ==
349 crypto_scalarmult_ed25519_base_noclamp (
350 sig_scal_mul_base.y,
351 sig->s_scalar.scalar.d));
352 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_dash_mul_pub.y,
353 c_dash.scalar.d,
354 pub->point.y));
355 GNUNET_assert (0 == crypto_core_ed25519_add (R_add_c_dash_mul_pub.y,
356 sig->r_point.point.y,
357 c_dash_mul_pub.y));
358
359 return 0 == GNUNET_memcmp (&sig_scal_mul_base,
360 &R_add_c_dash_mul_pub)
361 ? GNUNET_OK
363}
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static const unsigned char L_BIG_ENDIAN[32]
Definition: crypto_cs.c:136
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:209
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:151
static uint8_t seed
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_gnunet(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
A peculiar HKDF instantiation that tried to mimic Truncated NMAC.
Definition: crypto_hkdf.c:199
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:62
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:87
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:318
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:240
#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:330
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:284
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.