GNUnet  0.11.x
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 
48 void
50 {
51  crypto_core_ed25519_scalar_random (priv->scalar.d);
52 }
53 
54 
61 void
65 {
66  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (pub->point.y,
67  priv->scalar.d));
68 }
69 
70 
76 static void
78 {
79  // perform clamping as described in RFC7748
80  scalar->d[0] &= 248;
81  scalar->d[31] &= 127;
82  scalar->d[31] |= 64;
83 }
84 
85 
98 void
100  const struct GNUNET_CRYPTO_CsPrivateKey *lts,
101  struct GNUNET_CRYPTO_CsRSecret r[2])
102 {
105  sizeof (struct GNUNET_CRYPTO_CsRSecret)
106  * 2,
107  GCRY_MD_SHA512,
108  GCRY_MD_SHA256,
109  "r",
110  strlen ("r"),
111  lts,
112  sizeof (*lts),
113  nonce,
114  sizeof (*nonce),
115  NULL,
116  0));
117 
118  map_to_scalar_subgroup (&r[0].scalar);
119  map_to_scalar_subgroup (&r[1].scalar);
120 }
121 
122 
129 void
131  struct GNUNET_CRYPTO_CsRPublic *r_pub)
132 {
133  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (r_pub->point.y,
134  r_priv->scalar.d));
135 }
136 
137 
149 void
151  GNUNET_CRYPTO_CsNonce *blind_seed,
153  bs[2])
154 {
156  GNUNET_CRYPTO_hkdf (bs,
157  sizeof (struct
159  * 2,
160  GCRY_MD_SHA512,
161  GCRY_MD_SHA256,
162  "alphabeta",
163  strlen ("alphabeta"),
164  blind_seed,
165  sizeof(*blind_seed),
166  NULL,
167  0));
168  map_to_scalar_subgroup (&bs[0].alpha);
169  map_to_scalar_subgroup (&bs[0].beta);
170  map_to_scalar_subgroup (&bs[1].alpha);
171  map_to_scalar_subgroup (&bs[1].beta);
172 }
173 
174 
175 /*
176 order of subgroup required for scalars by libsodium
177 2^252 + 27742317777372353535851937790883648493
178 copied from https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
179 and converted to big endian
180 */
181 static const unsigned char L_BIG_ENDIAN[32] = {
182  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183  0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7,
184  0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed
185 };
186 
187 
195 static void
197  const void *msg,
198  size_t msg_len,
199  const struct GNUNET_CRYPTO_CsPublicKey *pub,
200  struct GNUNET_CRYPTO_CsC *c)
201 {
202  // SHA-512 hash of R' and message
203  size_t r_m_concat_len = sizeof(struct GNUNET_CRYPTO_CsRPublic) + msg_len;
204  char r_m_concat[r_m_concat_len];
205  memcpy (r_m_concat, r_dash, sizeof(struct GNUNET_CRYPTO_CsRPublic));
206  memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic), msg, msg_len);
207  struct GNUNET_HashCode prehash;
208  GNUNET_CRYPTO_hash (r_m_concat, r_m_concat_len, &prehash);
209 
210  // modulus converted to MPI representation
211  gcry_mpi_t l_mpi;
213 
214  // calculate full domain hash
215  gcry_mpi_t c_mpi;
217  l_mpi,
218  pub,
219  sizeof(struct GNUNET_CRYPTO_CsPublicKey),
220  &prehash,
221  sizeof(struct GNUNET_HashCode),
222  "Curve25519FDH");
223  gcry_mpi_release (l_mpi);
224 
225  // convert c from mpi
226  unsigned char c_big_endian[256 / 8];
227  GNUNET_CRYPTO_mpi_print_unsigned (c_big_endian, sizeof(c_big_endian), c_mpi);
228  gcry_mpi_release (c_mpi);
229  for (size_t i = 0; i<32; i++)
230  c->scalar.d[i] = c_big_endian[31 - i];
231 }
232 
233 
242 static void
244  const struct GNUNET_CRYPTO_CsRPublic *r_pub,
245  const struct GNUNET_CRYPTO_CsPublicKey *pub,
246  struct GNUNET_CRYPTO_CsRPublic *blinded_r_pub)
247 {
248  // R'i = Ri + alpha i*G + beta i*pub
249  struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base;
250  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
251  alpha_mul_base.y,
252  bs->alpha.d));
253  struct GNUNET_CRYPTO_Cs25519Point beta_mul_pub;
254  GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (beta_mul_pub.y,
255  bs->beta.d,
256  pub->point.y));
257  struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base_plus_beta_mul_pub;
258  GNUNET_assert (0 == crypto_core_ed25519_add (
259  alpha_mul_base_plus_beta_mul_pub.y,
260  alpha_mul_base.y,
261  beta_mul_pub.y));
262  GNUNET_assert (0 == crypto_core_ed25519_add (blinded_r_pub->point.y,
263  r_pub->point.y,
264  alpha_mul_base_plus_beta_mul_pub.
265  y));
266 }
267 
268 
281 void
283  bs[2],
284  const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
285  const struct GNUNET_CRYPTO_CsPublicKey *pub,
286  const void *msg,
287  size_t msg_len,
288  struct GNUNET_CRYPTO_CsC blinded_c[2],
290  blinded_r_pub[2])
291 {
292  // for i 0/1: R'i = Ri + alpha i*G + beta i*pub
293  calc_r_dash (&bs[0], &r_pub[0], pub, &blinded_r_pub[0]);
294  calc_r_dash (&bs[1], &r_pub[1], pub, &blinded_r_pub[1]);
295 
296  // for i 0/1: c'i = H(R'i, msg)
297  struct GNUNET_CRYPTO_CsC c_dash_0;
298  struct GNUNET_CRYPTO_CsC c_dash_1;
299  cs_full_domain_hash (&blinded_r_pub[0], msg, msg_len, pub, &c_dash_0);
300  cs_full_domain_hash (&blinded_r_pub[1], msg, msg_len, pub, &c_dash_1);
301 
302  // for i 0/1: ci = c'i + beta i mod p
303  crypto_core_ed25519_scalar_add (blinded_c[0].scalar.d,
304  c_dash_0.scalar.d,
305  bs[0].beta.d);
306  crypto_core_ed25519_scalar_add (blinded_c[1].scalar.d,
307  c_dash_1.scalar.d,
308  bs[1].beta.d);
309 }
310 
311 
328 unsigned int
330  const struct GNUNET_CRYPTO_CsRSecret r[2],
331  const struct GNUNET_CRYPTO_CsC c[2],
332  const struct GNUNET_CRYPTO_CsNonce *nonce,
333  struct GNUNET_CRYPTO_CsBlindS *
334  blinded_signature_scalar
335  )
336 {
337  uint32_t hkdf_out;
338 
339  // derive clause session identifier b (random bit)
341  GNUNET_CRYPTO_hkdf (&hkdf_out,
342  sizeof (hkdf_out),
343  GCRY_MD_SHA512,
344  GCRY_MD_SHA256,
345  "b",
346  strlen ("b"),
347  priv,
348  sizeof (*priv),
349  nonce,
350  sizeof (*nonce),
351  NULL,
352  0));
353  unsigned int b = hkdf_out % 2;
354 
355  // s = r_b + c_b priv
356  struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
357  crypto_core_ed25519_scalar_mul (c_b_mul_priv.d,
358  c[b].scalar.d,
359  priv->scalar.d);
360  crypto_core_ed25519_scalar_add (blinded_signature_scalar->scalar.d,
361  r[b].scalar.d,
362  c_b_mul_priv.d);
363 
364  return b;
365 }
366 
367 
375 void
377  GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
378  const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
379  struct GNUNET_CRYPTO_CsS *signature_scalar)
380 {
381  crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
382  blinded_signature_scalar->scalar.d,
383  bs->alpha.d);
384 }
385 
386 
399  const struct GNUNET_CRYPTO_CsPublicKey *pub,
400  const void *msg,
401  size_t msg_len)
402 {
403  // calculate c' = H(R, m)
404  struct GNUNET_CRYPTO_CsC c_dash;
405  cs_full_domain_hash (&sig->r_point, msg, msg_len, pub, &c_dash);
406 
407  // s'G ?= R' + c' pub
408  struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
409  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
410  sig_scal_mul_base.y,
411  sig->s_scalar.scalar.d));
412  struct GNUNET_CRYPTO_Cs25519Point c_dash_mul_pub;
413  GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_dash_mul_pub.y,
414  c_dash.scalar.d,
415  pub->point.y));
416  struct GNUNET_CRYPTO_Cs25519Point R_add_c_dash_mul_pub;
417  GNUNET_assert (0 == crypto_core_ed25519_add (R_add_c_dash_mul_pub.y,
418  sig->r_point.point.y,
419  c_dash_mul_pub.y));
420 
421  return 0 == GNUNET_memcmp (&sig_scal_mul_base,
422  &R_add_c_dash_mul_pub)
423  ? GNUNET_OK
424  : GNUNET_SYSERR;
425 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static const unsigned char L_BIG_ENDIAN[32]
Definition: crypto_cs.c:181
static void map_to_scalar_subgroup(struct GNUNET_CRYPTO_Cs25519Scalar *scalar)
maps 32 random bytes to a scalar this is necessary because libsodium expects scalar to be in the prim...
Definition: crypto_cs.c:77
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:243
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:130
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:150
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:62
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:376
void GNUNET_CRYPTO_cs_r_derive(const struct GNUNET_CRYPTO_CsNonce *nonce, 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:99
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:282
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:329
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:196
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:398
void GNUNET_CRYPTO_cs_private_key_generate(struct GNUNET_CRYPTO_CsPrivateKey *priv)
IMPLEMENTATION NOTICE:
Definition: crypto_cs.c:49
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.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:92
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
cryptographic primitives for GNUnet
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_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:127
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_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:343
#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.