GNUnet  0.17.6
crypto_cs.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2014,2016,2019 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 
27 #include "platform.h"
28 #include "gnunet_crypto_lib.h"
29 #include <sodium.h>
30 #include <gcrypt.h>
31 
43 void
45 {
46  crypto_core_ed25519_scalar_random (priv->scalar.d);
47 }
48 
49 
50 void
52  const struct GNUNET_CRYPTO_CsPrivateKey *priv,
54 {
55  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (pub->point.y,
56  priv->scalar.d));
57 }
58 
59 
66 static void
68 {
69  /* perform clamping as described in RFC7748 */
70  scalar->d[0] &= 248;
71  scalar->d[31] &= 127;
72  scalar->d[31] |= 64;
73 }
74 
75 
76 void
78  const char *seed,
79  const struct GNUNET_CRYPTO_CsPrivateKey *lts,
80  struct GNUNET_CRYPTO_CsRSecret r[2])
81 {
83  GNUNET_YES ==
85  r, sizeof (struct GNUNET_CRYPTO_CsRSecret) * 2,
86  seed, strlen (seed),
87  lts, sizeof (*lts),
88  nonce, sizeof (*nonce),
89  NULL, 0));
90  map_to_scalar_subgroup (&r[0].scalar);
91  map_to_scalar_subgroup (&r[1].scalar);
92 }
93 
94 
95 void
97  struct GNUNET_CRYPTO_CsRPublic *r_pub)
98 {
99  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (r_pub->point.y,
100  r_priv->scalar.d));
101 }
102 
103 
104 void
106  const struct GNUNET_CRYPTO_CsNonce *blind_seed,
107  struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
108 {
109  GNUNET_assert (
110  GNUNET_YES ==
111  GNUNET_CRYPTO_hkdf (bs,
112  sizeof (struct GNUNET_CRYPTO_CsBlindingSecret) * 2,
113  GCRY_MD_SHA512,
114  GCRY_MD_SHA256,
115  "alphabeta",
116  strlen ("alphabeta"),
117  blind_seed,
118  sizeof(*blind_seed),
119  NULL,
120  0));
121  map_to_scalar_subgroup (&bs[0].alpha);
122  map_to_scalar_subgroup (&bs[0].beta);
123  map_to_scalar_subgroup (&bs[1].alpha);
124  map_to_scalar_subgroup (&bs[1].beta);
125 }
126 
127 
128 /*
129 order of subgroup required for scalars by libsodium
130 2^252 + 27742317777372353535851937790883648493
131 copied from https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
132 and converted to big endian
133 */
134 static const unsigned char L_BIG_ENDIAN[32] = {
135  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136  0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7,
137  0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed
138 };
139 
140 
148 static void
150  const void *msg,
151  size_t msg_len,
152  const struct GNUNET_CRYPTO_CsPublicKey *pub,
153  struct GNUNET_CRYPTO_CsC *c)
154 {
155  // SHA-512 hash of R' and message
156  size_t r_m_concat_len = sizeof(struct GNUNET_CRYPTO_CsRPublic) + msg_len;
157  char r_m_concat[r_m_concat_len];
158  memcpy (r_m_concat, r_dash, sizeof(struct GNUNET_CRYPTO_CsRPublic));
159  memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic), msg, msg_len);
160  struct GNUNET_HashCode prehash;
161 
162  GNUNET_CRYPTO_hash (r_m_concat,
163  r_m_concat_len,
164  &prehash);
165 
166  // modulus converted to MPI representation
167  gcry_mpi_t l_mpi;
169  L_BIG_ENDIAN,
170  sizeof(L_BIG_ENDIAN));
171 
172  // calculate full domain hash
173  gcry_mpi_t c_mpi;
175  l_mpi,
176  pub,
177  sizeof(struct GNUNET_CRYPTO_CsPublicKey),
178  &prehash,
179  sizeof(struct GNUNET_HashCode),
180  "Curve25519FDH");
181  gcry_mpi_release (l_mpi);
182 
183  // convert c from mpi
184  unsigned char c_big_endian[256 / 8];
185  GNUNET_CRYPTO_mpi_print_unsigned (c_big_endian,
186  sizeof(c_big_endian),
187  c_mpi);
188  gcry_mpi_release (c_mpi);
189  for (size_t i = 0; i<32; i++)
190  c->scalar.d[i] = c_big_endian[31 - i];
191 }
192 
193 
202 static void
204  const struct GNUNET_CRYPTO_CsRPublic *r_pub,
205  const struct GNUNET_CRYPTO_CsPublicKey *pub,
206  struct GNUNET_CRYPTO_CsRPublic *blinded_r_pub)
207 {
208  // R'i = Ri + alpha i*G + beta i*pub
209  struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base;
210  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
211  alpha_mul_base.y,
212  bs->alpha.d));
213  struct GNUNET_CRYPTO_Cs25519Point beta_mul_pub;
214  GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (beta_mul_pub.y,
215  bs->beta.d,
216  pub->point.y));
217  struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base_plus_beta_mul_pub;
218  GNUNET_assert (0 == crypto_core_ed25519_add (
219  alpha_mul_base_plus_beta_mul_pub.y,
220  alpha_mul_base.y,
221  beta_mul_pub.y));
222  GNUNET_assert (0 == crypto_core_ed25519_add (blinded_r_pub->point.y,
223  r_pub->point.y,
224  alpha_mul_base_plus_beta_mul_pub.
225  y));
226 }
227 
228 
229 void
231  const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
232  const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
233  const struct GNUNET_CRYPTO_CsPublicKey *pub,
234  const void *msg,
235  size_t msg_len,
236  struct GNUNET_CRYPTO_CsC blinded_c[2],
237  struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2])
238 {
239  // for i 0/1: R'i = Ri + alpha i*G + beta i*pub
240  calc_r_dash (&bs[0], &r_pub[0], pub, &blinded_r_pub[0]);
241  calc_r_dash (&bs[1], &r_pub[1], pub, &blinded_r_pub[1]);
242 
243  // for i 0/1: c'i = H(R'i, msg)
244  struct GNUNET_CRYPTO_CsC c_dash_0;
245  struct GNUNET_CRYPTO_CsC c_dash_1;
246  cs_full_domain_hash (&blinded_r_pub[0], msg, msg_len, pub, &c_dash_0);
247  cs_full_domain_hash (&blinded_r_pub[1], msg, msg_len, pub, &c_dash_1);
248 
249  // for i 0/1: ci = c'i + beta i mod p
250  crypto_core_ed25519_scalar_add (blinded_c[0].scalar.d,
251  c_dash_0.scalar.d,
252  bs[0].beta.d);
253  crypto_core_ed25519_scalar_add (blinded_c[1].scalar.d,
254  c_dash_1.scalar.d,
255  bs[1].beta.d);
256 }
257 
258 
259 unsigned int
261  const struct GNUNET_CRYPTO_CsPrivateKey *priv,
262  const struct GNUNET_CRYPTO_CsRSecret r[2],
263  const struct GNUNET_CRYPTO_CsC c[2],
264  const struct GNUNET_CRYPTO_CsNonce *nonce,
265  struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar)
266 {
267  uint32_t hkdf_out;
268 
269  // derive clause session identifier b (random bit)
271  GNUNET_CRYPTO_hkdf (&hkdf_out,
272  sizeof (hkdf_out),
273  GCRY_MD_SHA512,
274  GCRY_MD_SHA256,
275  "b",
276  strlen ("b"),
277  priv,
278  sizeof (*priv),
279  nonce,
280  sizeof (*nonce),
281  NULL,
282  0));
283  unsigned int b = hkdf_out % 2;
284 
285  // s = r_b + c_b priv
286  struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
287  crypto_core_ed25519_scalar_mul (c_b_mul_priv.d,
288  c[b].scalar.d,
289  priv->scalar.d);
290  crypto_core_ed25519_scalar_add (blinded_signature_scalar->scalar.d,
291  r[b].scalar.d,
292  c_b_mul_priv.d);
293 
294  return b;
295 }
296 
297 
298 void
300  const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
301  const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
302  struct GNUNET_CRYPTO_CsS *signature_scalar)
303 {
304  crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
305  blinded_signature_scalar->scalar.d,
306  bs->alpha.d);
307 }
308 
309 
312  const struct GNUNET_CRYPTO_CsPublicKey *pub,
313  const void *msg,
314  size_t msg_len)
315 {
316  // calculate c' = H(R, m)
317  struct GNUNET_CRYPTO_CsC c_dash;
318 
320  msg,
321  msg_len,
322  pub,
323  &c_dash);
324 
325  // s'G ?= R' + c' pub
326  struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
327  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
328  sig_scal_mul_base.y,
329  sig->s_scalar.scalar.d));
330  struct GNUNET_CRYPTO_Cs25519Point c_dash_mul_pub;
331  GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_dash_mul_pub.y,
332  c_dash.scalar.d,
333  pub->point.y));
334  struct GNUNET_CRYPTO_Cs25519Point R_add_c_dash_mul_pub;
335  GNUNET_assert (0 == crypto_core_ed25519_add (R_add_c_dash_mul_pub.y,
336  sig->r_point.point.y,
337  c_dash_mul_pub.y));
338 
339  return 0 == GNUNET_memcmp (&sig_scal_mul_base,
340  &R_add_c_dash_mul_pub)
341  ? GNUNET_OK
342  : GNUNET_SYSERR;
343 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static const unsigned char L_BIG_ENDIAN[32]
Definition: crypto_cs.c:134
static void map_to_scalar_subgroup(struct GNUNET_CRYPTO_Cs25519Scalar *scalar)
Maps 32 random bytes to a scalar.
Definition: crypto_cs.c:67
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:203
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:149
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:46
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.
cryptographic primitives for GNUnet
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:340
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:69
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:131
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:96
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:94
void GNUNET_CRYPTO_cs_blinding_secrets_derive(const struct GNUNET_CRYPTO_CsNonce *blind_seed, struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
Derives new random blinding factors.
Definition: crypto_cs.c:105
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:51
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:299
void GNUNET_CRYPTO_cs_r_derive(const struct GNUNET_CRYPTO_CsNonce *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:77
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:78
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_CsRPublic blinded_r_pub[2])
Calculate two blinded c's Comment: One would be insecure due to Wagner's algorithm solving ROS.
Definition: crypto_cs.c:230
unsigned int GNUNET_CRYPTO_cs_sign_derive(const struct GNUNET_CRYPTO_CsPrivateKey *priv, const struct GNUNET_CRYPTO_CsRSecret r[2], const struct GNUNET_CRYPTO_CsC c[2], const struct GNUNET_CRYPTO_CsNonce *nonce, struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar)
Sign a blinded c This function derives b from a nonce and a longterm secret In original papers b is g...
Definition: crypto_cs.c:260
#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:311
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:96
void GNUNET_CRYPTO_cs_private_key_generate(struct GNUNET_CRYPTO_CsPrivateKey *priv)
IMPLEMENTATION NOTICE:
Definition: crypto_cs.c:44
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
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
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
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
A 512-bit hashcode.