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